I'm converting a simple ThinkScript strategy to Pine Script. In ThinkScript, it opens many trades over the past few days (5-minute chart on SPY ticker), but when translated to Pine Script, there are no trades placed. Wondering if someone can spot the bug. Note, it uses request.security
to get data from a higher timeframe/aggregation, not sure if that's the issue or not.
This is the ThinkScript:
input agg = AggregationPeriod.HOUR; input TrendPeriods = 5;input use_trading_hours = yes;input spread = 0.15;####################################################### TIME######################################################def startTradingTime = if use_trading_hours == yes then 0930 else 0000;def noMorePositions = if use_trading_hours == yes then 1530 else 0000;def endTradingTime = if use_trading_hours == yes then 1600 else 0000;def isTradingSession = if use_trading_hours == yes then SecondsFromTime(startTradingTime) >= 0 and SecondsTillTime(endTradingTime) > 0 else yes;def positionsStillAllowed = if use_trading_hours == yes then SecondsTillTime(noMorePositions) > 0 else yes;def h = high(period = agg); def l = low(period = agg); def c = close(period = agg); def hh = highest(h, trendPeriods); def ll = lowest(l, trendPeriods); def trend = if ((c - ll) / (hh - ll)) > .5 then 1 else 0; // Enter long (flip from short if necessary)addorder(orderType.BUY_AUTO, trend[1] and isTradingSession and positionsStillAllowed and BarNumber()>1, tradesize=1, price=open[-1]+spread); // Exit long at EODaddorder(orderType.SELL_TO_CLOSE, !isTradingSession[-1], tradesize=1, price=open-spread); // Enter short (flip from long if necessary)addorder(orderType.SELL_AUTO, !trend[1] and isTradingSession and positionsStillAllowed and BarNumber()>1, tradesize=1, price=open[-1]-spread); // Exit short at EODaddorder(orderType.BUY_TO_CLOSE, !isTradingSession[-1], tradesize=1, price=open+spread);
Due to looking at higher aggregation/timeframe, I use trend[1] to get the previous, fully closed trend
value to act on the current bar re: repainting.
This is my Pine Script so far that generates no trades in the Strategy Tester, yet shows no syntax or compile errors:
// © windowshopr//@version=5//=========================== IMPORTS AND STRATEGY ===========================//strategy("My Strategy", shorttitle="My Strategy", overlay=true, initial_capital=1000, pyramiding=1, calc_on_order_fills=true, calc_on_every_tick=true, backtest_fill_limits_assumption=10, default_qty_type=strategy.percent_of_equity, default_qty_value=100, currency=currency.NONE, slippage=1, commission_type=strategy.commission.cash_per_contract, commission_value=0.01)//=========================== INPUTS ===========================////========= STRATEGYinput_agg_period = input.timeframe(title = "Higher TimeFrame Aggregation Period", defval = "60", group = 'Strategy',tooltip = 'The higher timeframe to use with strategy')input_trend_periods = input.int(title = "Trend Periods", minval = 1, defval = 5, group = 'Strategy',tooltip = 'The number of bars/periods to use for calculating trend')//=========================== STRATEGY ===========================//var float h = request.security(syminfo.tickerid, input_agg_period, high)var float l = request.security(syminfo.tickerid, input_agg_period, low)var float c = request.security(syminfo.tickerid, input_agg_period, close)var float hh = ta.highest(h, input_trend_periods)var float ll = ta.lowest(l, input_trend_periods)var int trend = ((c - ll) / (hh - ll)) > .5 ? 1 : 0longCondition = trend[1] == 1shortCondition = trend[1] == 0//=========================== TIME MANAGEMENT ===========================//// InSession() returns 'true' when the current bar happens inside// the specified session, corrected for the given time zone (optional).// Returns 'false' when the bar doesn't happen in that time period,// or when the chart's time frame is 1 day or higher. InSession(sessionTime, sessionTimeZone=syminfo.timezone) =>not na(time(timeframe.period, sessionTime, sessionTimeZone))session = input.session("0730-1400", title="Session")timeZone = input.string("GMT-6", title="Time Zone")var bool inRTH = InSession(session, timeZone) //=========================== TRADE MANAGEMENT ===========================//bool openLongPosition = longCondition and inRTHbool openShortPosition = shortCondition and inRTHbool closeLongPosition = shortCondition or not inRTHbool closeShortPosition = longCondition or not inRTHbool longIsActive = openLongPosition or strategy.position_size > 0 and not closeLongPositionbool shortIsActive = openShortPosition or strategy.position_size < 0 and not closeShortPosition// the open signals when not already into a positionbool validOpenLongPosition = openLongPosition and not (strategy.position_size > 0)bool validOpenShortPosition = openShortPosition and not (strategy.position_size < 0)// Order Exitsif closeLongPosition and longIsActivestrategy.close(id = 'Long Entry', comment = 'Close Long', alert_message = 'Long: Closed at market price')// close on trend reversalif closeShortPosition and shortIsActivestrategy.close(id = 'Short Entry', comment = 'Close Short', alert_message = 'Short: Closed at market price')// Order Entriesif validOpenLongPositionstrategy.entry(id = 'Long Entry', direction = strategy.long, alert_message = 'Long(' + syminfo.ticker + '): Started')// getting into SHORT positionif validOpenShortPositionstrategy.entry(id = 'Short Entry', direction = strategy.short, alert_message = 'Short(' + syminfo.ticker + '): Started')
Note that if you comment out the RTH/InSession logic from the entry/exit conditions, it opens 1 trade, however I'm trying to get a 1:1 match from ThinkOrSwim, and it trades almost daily over the past few weeks. Can you spot the issue?
Best Answer
I've discovered that you CANNOT use the var float
declarations if you want to use variable values on a global scope, var <type>
is meant for local scopes.
The updated code looks like this:
//=========================== STRATEGY ===========================//h = request.security(syminfo.ticker, input_agg_period, high)l = request.security(syminfo.ticker, input_agg_period, low)c = request.security(syminfo.ticker, input_agg_period, close)hh = ta.highest(h, input_trend_periods)ll = ta.lowest(l, input_trend_periods)// If "trend" > 0.5, then true/uptrend, else false/downtrendtrendSignal = (c - ll) / (hh - ll) > 0.5 ? 1 : 0// Update the bar colours for visual inspectionbarcolor(trendSignal[1] == 1 ? color.blue : color.red)// Define some potential entry conditionslongCondition = trendSignal[1] == 1shortCondition = trendSignal[1] == 0