Deeper dive into Relational Operators
Deeper dive into Relational Operators
Relational operators compare two values and return a boolean result (true or false). They are fundamental to decision-making in HaasScript strategies.
Overview of Relational Operators
HaasScript provides six relational operators:
| Operator | Description | Example |
|---|---|---|
== |
Equal to | a == b |
~= |
Not equal to | a ~= b |
< |
Less than | a < b |
> |
Greater than | a > b |
<= |
Less than or equal to | a <= b |
>= |
Greater than or equal to | a >= b |
Equality Operators
Equal To (==)
Checks if two values are exactly the same:
local rsi = 30
local threshold = 30
if rsi == threshold then
Log("RSI is exactly at threshold")
end
Not Equal To (~=)
Checks if two values are different:
local currentSignal = SignalLong
local expectedSignal = SignalShort
if currentSignal ~= expectedSignal then
Log("Signals don't match")
end
Important: HaasScript uses ~= for "not equal", not != like many other languages:
-- Wrong
if a != b then -- Error: invalid operator
-- Correct
if a ~= b then -- Works correctly
Comparison Operators
Less Than (<)
local rsi = 25
local oversoldLevel = 30
if rsi < oversoldLevel then
DoLong("RSI oversold")
end
Greater Than (>)
local rsi = 75
local overboughtLevel = 70
if rsi > overboughtLevel then
DoShort("RSI overbought")
end
Less Than or Equal To (<=)
local price = 45000
local targetPrice = 45000
if price <= targetPrice then
DoLong("Price at or below target")
end
Greater Than or Equal To (>=)
local price = 46000
local stopPrice = 45000
if price >= stopPrice then
DoExitPosition("Stop loss hit")
end
Comparing Different Data Types
Numbers
Number comparisons work as expected:
local currentPrice = 45000
local entryPrice = 44000
if currentPrice > entryPrice then
Log("Price increased since entry")
end
local percentage = 2.5
if percentage >= 2.0 then
Log("Risk percentage acceptable")
end
Strings
Strings are compared alphabetically:
local market1 = "BTC_USDT"
local market2 = "ETH_USDT"
if market1 < market2 then
Log("BTC comes before ETH alphabetically")
end
local market1 = "BTC_USDT"
local market2 = "BTC_USDT"
if market1 == market2 then
Log("Markets are the same")
end
Important: String comparisons are case-sensitive:
local text1 = "BTC"
local text2 = "btc"
if text1 == text2 then
-- This is FALSE (case mismatch)
end
if text1 ~= text2 then
-- This is TRUE (different cases)
end
Booleans
Boolean comparisons are straightforward:
local inLong = HasLongPosition()
local inShort = HasShortPosition()
if inLong == true then
-- Equivalent to: if inLong then
Log("In long position")
end
if inShort ~= true then
-- Equivalent to: if not inShort then
Log("Not in short position")
end
Signals
Signal constants can be compared:
local currentSignal = SignalLong
local expectedSignal = SignalLong
if currentSignal == expectedSignal then
DoSignal(currentSignal)
end
Collections
Collections use the latest value (index 1) when compared:
local closePrices = ClosePrices()
local threshold = 45000
-- Compares latest close price to threshold
if closePrices > threshold then
DoLong("Price above threshold")
end
-- This is equivalent to:
if closePrices[1] > threshold then
DoLong("Price above threshold")
end
Common Trading Patterns
RSI Thresholds
local rsi = RSI(ClosePrices(), 14)
if rsi <= 30 then
DoLong("RSI oversold")
elseif rsi >= 70 then
DoShort("RSI overbought")
end
Moving Average Crossover
local fastMA = EMA(ClosePrices(), 9)
local slowMA = EMA(ClosePrices(), 21)
if fastMA > slowMA then
Log("Uptrend - fast MA above slow MA")
elseif fastMA < slowMA then
Log("Downtrend - fast MA below slow MA")
end
Price Level Checks
local currentPrice = ClosePrices()
local supportLevel = 44000
local resistanceLevel = 46000
if currentPrice <= supportLevel then
DoLong("Price at support")
elseif currentPrice >= resistanceLevel then
DoShort("Price at resistance")
end
Percentage-Based Conditions
local entryPrice = 45000
local currentPrice = ClosePrices()
local profitTarget = 5.0 -- 5%
local profitPercentage = ((currentPrice - entryPrice) / entryPrice) * 100
if profitPercentage >= profitTarget then
DoExitPosition("Take profit reached")
end
ATR-Based Comparisons
local atr = ATR(HighPrices(), LowPrices(), ClosePrices(), 14)
local currentPrice = ClosePrices()
local atrPercentage = (atr / currentPrice) * 100
if atrPercentage > 2.0 then
Log("High volatility - tighten stops")
end
Combining with Logical Operators
Relational operators are often combined with logical operators:
local rsi = RSI(ClosePrices(), 14)
local macd = MACD(ClosePrices(), 12, 26, 9)
-- Both conditions must be true (AND)
if rsi < 30 and macd == SignalLong then
DoLong("RSI oversold + MACD confirmation")
end
-- At least one condition must be true (OR)
if rsi > 70 or rsi < 30 then
Log("RSI at extreme levels")
end
-- Negate a condition (NOT)
if not (rsi >= 30 and rsi <= 70) then
Log("RSI outside normal range")
end
Common Mistakes
Assignment vs Comparison
-- Wrong: Using = for comparison
if rsi = 30 then -- Error: = is assignment, not comparison
DoLong()
end
-- Correct: Using == for comparison
if rsi == 30 then
DoLong()
end
Wrong Not-Equal Operator
-- Wrong: Using != for not equal
if rsi != 30 then -- Error: invalid operator
DoLong()
end
-- Correct: Using ~= for not equal
if rsi ~= 30 then
DoLong()
end
Case-Sensitive String Comparisons
local market = "BTC_USDT"
-- Wrong: Case doesn't match
if market == "btc_usdt" then -- This is FALSE
DoLong()
end
-- Correct: Exact case match
if market == "BTC_USDT" then -- This is TRUE
DoLong()
end
Comparing Different Types
local number = 100
local text = "100"
-- These are NOT equal
if number == text then -- This is FALSE
Log("They are equal")
end
-- Correct: Convert to same type first
if tostring(number) == text then
Log("They are equal")
end
Floating-Point Precision
local result = 0.1 + 0.2 -- May be 0.30000000000000004
-- Problematic: Exact comparison
if result == 0.3 then -- Might be FALSE due to precision
Log("Equal")
end
-- Better: Use tolerance or rounding
if math.abs(result - 0.3) < 0.0001 then
Log("Equal within tolerance")
end
Collection Comparisons
local prices1 = ClosePrices()
local prices2 = ClosePrices()
-- This compares the collection objects, not their values
if prices1 == prices2 then
-- This is TRUE (they reference the same collection)
end
-- To compare values, compare specific elements
if prices1[1] == prices2[1] then
-- Compares latest prices
end
Operator Precedence
Relational operators have lower precedence than arithmetic operators:
local result = 5 + 3 > 7 -- Evaluated as: (5 + 3) > 7 = 8 > 7 = true
-- When in doubt, use parentheses
local result = (5 + 3) > 7 -- Clearer
Short-Circuit Evaluation
When combining conditions, HaasScript uses short-circuit evaluation:
local rsi = RSI(ClosePrices(), 14)
local expensiveCalculation = ComplexFunction()
-- If rsi < 30 is FALSE, expensiveCalculation() is never called
if rsi < 30 and expensiveCalculation() then
DoLong()
end
-- If rsi > 70 is TRUE, expensiveCalculation() is never called
if rsi > 70 or expensiveCalculation() then
DoLong()
end
This can improve performance when you have expensive calculations.
Practical Examples
Example 1: Multi-Condition Entry
local rsi = RSI(ClosePrices(), 14)
local macd = MACD(ClosePrices(), 12, 26, 9)
local volume = Volume()
local avgVolume = SMA(volume, 20)
-- Entry requires ALL conditions
if rsi < 30 and macd == SignalLong and volume > avgVolume then
DoLong("Multiple indicators confirm entry")
end
Example 2: Trailing Stop
local entryPrice = 45000
local currentPrice = ClosePrices()
local trailPercent = 2.0
local highestPrice = entryPrice
local trailingStop = highestPrice * (1 - trailPercent / 100)
if currentPrice > highestPrice then
highestPrice = currentPrice -- Update highest
trailingStop = highestPrice * (1 - trailPercent / 100)
end
if currentPrice <= trailingStop then
DoExitPosition("Trailing stop hit")
end
Example 3: Range Breakout
local closePrices = ClosePrices()
local highPrices = HighPrices()
local lowPrices = LowPrices()
local lookback = 20
local highestHigh = Max(highPrices, lookback)
local lowestLow = Min(lowPrices, lookback)
if closePrices > highestHigh then
DoLong("Breakout above range")
elseif closePrices < lowestLow then
DoShort("Breakout below range")
end
Example 4: Volatility Filter
local atr = ATR(HighPrices(), LowPrices(), ClosePrices(), 14)
local atrPercentage = (atr / ClosePrices()) * 100
local lowVolThreshold = 1.0
local highVolThreshold = 3.0
if atrPercentage <= lowVolThreshold then
Log("Low volatility - use wider stops")
elseif atrPercentage >= highVolThreshold then
Log("High volatility - reduce position size")
else
Log("Normal volatility")
end
Best Practices
- Use parentheses for complex conditions to improve clarity
- Combine related conditions with logical operators for filtering
- Be careful with floating-point comparisons - use tolerance when needed
- Remember case sensitivity when comparing strings
-
Use
~=not!=for not-equal comparisons -
Don't use
=for comparison - use== - Test edge cases like exact threshold values
- Consider short-circuit evaluation when optimizing performance
Summary
-
Six relational operators:
==,~=,<,>,<=,>= -
Return boolean values (
trueorfalse) - Compare various types: numbers, strings, booleans, signals, collections
- Common patterns: threshold checks, crossovers, price levels
-
Combine with logical operators:
and,or,not - Avoid common mistakes: wrong operators, type mismatches, precision issues
- Use parentheses for clarity in complex conditions
Relational operators are the foundation of decision-making in HaasScript. Master them to create sophisticated trading logic that responds to market conditions accurately.