Python Part 1 - Introduction
Converting from Python to HaasScript
This is the most involved conversion because Python and HaasScript operate on fundamentally different paradigms. PineScript and Lua share syntax and execution models with HaasScript, but Python strategies typically process dataframes of historical bars, call exchange APIs directly, and run as standalone scripts. HaasScript does none of that.
This page covers the paradigm shift. For a full annotated conversion, see Strategy Conversion. For how specific Python patterns map conceptually, see Common Patterns.
The Core Difference
Python trading strategies typically follow this pattern:
# Load historical data
df = exchange.fetch_ohlcv('BTC/USDT', '1h', limit=500)
df = pd.DataFrame(df, columns=['time', 'open', 'high', 'low', 'close', 'volume'])
# Calculate indicators on the full dataset
df['rsi'] = ta.rsi(df['close'], 14)
df['ema'] = ta.ema(df['close'], 50)
# Iterate and find signals
for i in range(len(df)):
if df['rsi'][i] < 30 and df['close'][i] > df['ema'][i]:
exchange.create_market_buy_order('BTC/USDT', amount)
# Manage positions
if position:
exchange.create_order('BTC/USDT', 'limit', 'sell', amount, stop_price=stop)
HaasScript follows this pattern:
local closePrices = ClosePrices()
local rsi = RSI(closePrices, 14)
local ema = EMA(closePrices, 50)
if rsi < 30 and closePrices > ema and GetPositionDirection() == NoPosition then
DoLong()
end
StopLoss(2.5)
TakeProfit(5.0)
The differences are not cosmetic — they are structural:
- No dataframes. HaasScript does not load or process historical bars in bulk. Indicators calculate automatically on each tick from data the platform provides.
-
No exchange API calls. You never call
create_market_buy_order()or any exchange function. The bot platform handles order execution. You generate signals. -
No iteration over bars. Your code runs once per tick. There is no
forloop over historical data. -
No position tracking objects. The platform tracks positions. You query state with
GetPositionDirection()and manage risk withStopLoss()/TakeProfit().
What You Lose
These Python patterns have no direct equivalent in HaasScript:
| Python Concept | Why It Does Not Exist |
|---|---|
pandas DataFrame operations |
HaasScript processes one tick at a time, not bulk data |
ccxt / exchange API calls |
The platform manages all exchange communication |
| Custom order routing | Managed trading handles execution; unmanaged trading provides limited control |
Async loops / asyncio
|
Execution is synchronous per tick |
| Background threads / schedulers | The platform invokes your script on a schedule |
| File I/O for data persistence | Use Save() and Load() for state between ticks |
| Web scraping / external API calls | Network access is restricted |
import / third-party packages |
No module system — only built-in commands |
What Changes
Indicator Calculation
In Python, you compute indicators on a dataframe and access results by row index. In HaasScript, you call the indicator function and it returns the current value automatically:
# Python: compute on full history, access by index
df['rsi'] = ta.rsi(df['close'], 14)
current_rsi = df['rsi'].iloc[-1]
previous_rsi = df['rsi'].iloc[-2]
-- HaasScript: call the function, get current value
local rsi = RSI(ClosePrices(), 14)
-- rsi resolves to the latest value automatically in comparisons
-- For historical values, access by index (1 = latest)
local currentRSI = rsi[1]
local previousRSI = rsi[2]
Entry and Exit
Python strategies typically place orders directly through an exchange library. HaasScript generates signals that the bot platform executes:
# Python
exchange.create_market_buy_order('BTC/USDT', 0.1)
exchange.create_order('BTC/USDT', type='stop_loss', amount=0.1, price=stop_price)
-- HaasScript
DoLong()
StopLoss(2.5) -- percentage, not price
The bot handles order placement, execution, position sizing, and exchange communication. Your script decides when to trade, not how.
Risk Management
Python strategies often implement stop losses as manual price checks or exchange-side orders. In HaasScript, risk management is declarative:
# Python: manual stop loss check
if position and current_price <= stop_price:
exchange.create_market_sell_order('BTC/USDT', position['amount'])
-- HaasScript: declarative, runs automatically
StopLoss(2.5)
TakeProfit(5.0)
TrailingStopLoss(1.5)
Call these once and the bot monitors them on every tick. No manual price checking needed.
Multi-Timeframe Analysis
Python strategies often resample dataframes to different timeframes:
# Python
df_1h = df.resample('1h').agg({'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last'})
df_daily = df.resample('1D').agg({'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last'})
HaasScript handles this through the interval parameter on price data functions:
local hourlyClose = ClosePrices(60)
local dailyClose = ClosePrices(1440)
local hourlyRSI = RSI(hourlyClose, 14)
local dailyEMA = EMA(dailyClose, 50)
State Persistence
Python strategies often use global variables, class instances, or databases to maintain state between runs. HaasScript uses Save() and Load():
# Python
class Strategy:
def __init__(self):
self.trade_count = 0
def on_tick(self):
self.trade_count += 1
-- HaasScript
local tradeCount = Load('tradeCount', 0)
tradeCount = tradeCount + 1
Save('tradeCount', tradeCount)
What You Gain
HaasScript removes the infrastructure burden. In a Python setup, you are responsible for:
- Exchange API connections and error handling
- WebSocket management for real-time data
- Order submission, tracking, and reconciliation
- Position state management
- Backtesting infrastructure
- Deployment and monitoring
HaasScript handles all of this through the TradeServer platform. Your script focuses entirely on trading logic — indicators, conditions, and risk parameters.
What Transfers Directly
Some Python concepts map cleanly:
-
Conditional logic —
if/elif/elsebecomesif/elseif/else -
Boolean operators —
and,or,notare the same in Lua -
Arithmetic —
+,-,*,/,%all work the same -
Variable assignment —
x = 10works in Lua (uselocal x = 10) -
String concatenation —
f"RSI: {value}"becomes'RSI: ' .. value -
Math functions —
math.abs(),math.sqrt()are available in Lua'smath.*library, with HaasScript equivalents that handle collections
Syntax Quick Reference
| Python | HaasScript / Lua | Notes |
|---|---|---|
x = 10 |
local x = 10 |
local scopes the variable |
# comment |
-- comment |
Different comment syntax |
elif |
elseif |
One word, no space |
== / != / > / <
|
== / ~= / > / <
|
Not-equal uses ~=
|
and / or / not
|
and / or / not
|
Same keywords |
True / False
|
true / false
|
Lowercase |
None |
nil |
Different keyword |
"text" + str(x) |
"text" .. tostring(x) |
.. concatenates |
f"{x}" |
tostring(x) or .. concatenation |
No f-strings |
len(arr) |
Count(arr) |
HaasScript command |
arr[-1] |
arr[1] |
HaasScript: 1 = latest, no negative indexing |
for i in range(n) |
for i = 1, n do |
Inclusive upper bound |
while condition: |
while condition do |
Ends with end
|
def func(x): |
local function func(x) |
Ends with end
|
import math |
Not available | Use built-in commands or math.*
|
class |
Not available | Use Save()/Load() for state |
When Python Strategies Need Rethinking
Some Python strategy patterns do not translate cleanly and need a different approach:
-
Machine learning models — You cannot import
scikit-learnortensorflow. HaasScript has no ML library. These strategies stay in Python. - Statistical arbitrage across hundreds of pairs — HaasScript runs per-bot on a single market. Cross-market analysis requires multiple bots coordinated externally.
- Custom order types or routing — If your edge is in execution (TWAP, VWAP, iceberg orders), the managed trading model abstracts away the details you need.
- Real-time data pipelines — If you consume order book L2 data, liquidations, or funding rates directly, HaasScript works at the candle/tick level, not the order book level.
HaasScript is best suited for indicator-based, rule-driven strategies on a single market — the kind of logic that makes up the majority of retail trading bots.