$SPY Swing Strategy

quijanoj

New member
Entering at the signal bars is not realistic. You will need to wait for the bar to close in order to put your order in because the signals car repaint in the same bar. Usually, backtesting is done with the open price of the following bar of the signals bar.
That makes sense, thank you... it means that if I plot the arrow Up/down signal at open, not at high or low... it might repaint but I will not need to wait until the candle closes, right?
 
Last edited:
@barbaros Thank you for converting this to TOS - I did some backtesting today and results are consistently good across time frames. Moreover, I also backtested this along with B4 indicators and believe winrate actually improves when combined (i.e. losing trades could have been avoided applying rules from B4 system).

One question: are you aware of Trading view script for this?
 

barbaros

Administrator
Staff member
@barbaros Thank you for converting this to TOS - I did some backtesting today and results are consistently good across time frames. Moreover, I also backtested this along with B4 indicators and believe winrate actually improves when combined (i.e. losing trades could have been avoided applying rules from B4 system).

One question: are you aware of Trading view script for this?
Did you test with the complete B4 system or just the B4 indicator? I would love to chat with you about it on our Discord to see your results.

There isn’t a TradingView indicator but I can convert it for you.
 
Did you test with the complete B4 system or just the B4 indicator? I would love to chat with you about it on our Discord to see your results.

There isn’t a TradingView indicator but I can convert it for you.

I tested it with entire B4 system and could use the system to either avoid entering the trade and/or cut the losses early resulting in capital prevention. For e.g. With Upstart, since 1/20, there were 19 trades recommended on 10 mins chart. 16 of these were already profitable and 3 were not. For these 3 unsuccessful trade, I could justify not entering or exiting early based on B4 system/rules. Happy to take this to discord with examples/screenshots.

Regarding Tradingview, would be great if you can help convert as strategy cum indicator. Also, if that is too much of effort - I want to be respectful of your time.

Thank you
 

barbaros

Administrator
Staff member
I tested it with entire B4 system and could use the system to either avoid entering the trade and/or cut the losses early resulting in capital prevention. For e.g. With Upstart, since 1/20, there were 19 trades recommended on 10 mins chart. 16 of these were already profitable and 3 were not. For these 3 unsuccessful trade, I could justify not entering or exiting early based on B4 system/rules. Happy to take this to discord with examples/screenshots.

Regarding Tradingview, would be great if you can help convert as strategy cum indicator. Also, if that is too much of effort - I want to be respectful of your time.

Thank you
That’s awesome!!!

I will convert it to TradingView shortly.
 

barbaros

Administrator
Staff member
@workingprogrammer here is the TradingView conversion.

It is published and available here: https://www.tradingview.com/script/KVDjl4y6-SPY-Swing-Strategy/

Code is open but publishing it here too.
Code:
// SPY Swing Strategy / Daily Trader
// Free for use. Header credits must be included when any form of the code included in this package is used.
// v1.0 - barbaros - converted for b4signals.com / https://b4indicators.com/threads/spy-swing-strategy.137/

//@version=5
strategy("SPY Swing Strategy", overlay=true, initial_capital=1000)

initialBalance = strategy.initial_capital
atrPeriods = input.int(10, "ATR Periods")
lowest_close = input.int(3, "Lowest Close")
trend_average = input.int(66, "Trend Average")
highest_close = input.int(19, "Highest Close")
stop_var = input.float(7.95, "Stop Var")
targetWinRate = input.float(1, "Target Win Rate")
targetWinLoss = input.float(.50, "Target Win/Loss")
useMoneyManagement = input.bool(true, "Use Money Management")
intradayOnly = input.bool(false, "Intraday Only")

FPL = strategy.grossprofit
entry = strategy.opentrades.entry_price(strategy.opentrades - 1)

isTrade = not intradayOnly

atrA = ta.sma(math.abs(close - close[1]), atrPeriods)
atr = atrA < 1 ? 1 : atrA

portfolioSize = not na(FPL) ? FPL + initialBalance : initialBalance
contractsToTrade = useMoneyManagement ? math.floor(portfolioSize / (atr * close)) : 1

buyCond = close <= ta.lowest(close, lowest_close) and close > ta.sma(close, trend_average)
sellCond = close >= ta.highest(close, highest_close)

direction = 0
direction := bar_index == 1 ? 0 :
     direction[1] == 0 and buyCond and contractsToTrade > 0 ? 1 :
     direction[1] == 1 and sellCond ? 0 :
     direction[1]

stop_price = close
stop_price := ta.cross(direction, 0) ? close - (stop_var * atr) : stop_price[1]

plotshape(direction == 1 and direction != direction[1], title="Buy Signal", text="Buy", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.black, size=size.normal)
plotshape(direction == 0 and direction != direction[1], title="Exit Signal", text="Exit", style=shape.labeldown, location=location.abovebar, color=color.gray, textcolor=color.black, size=size.normal)

strategy.order("LONG", strategy.long, contractsToTrade, when = isTrade and ta.crossover(direction, 0))
strategy.close("LONG", when = not isTrade or ta.crossunder(direction, 1), comment = "EXIT")
 

barbaros

Administrator
Staff member
Added HUD for status for TradingView version.

Code:
// SPY Swing Strategy / Daily Trader
// Free for use. Header credits must be included when any form of the code included in this package is used.
// v1.0 - barbaros - converted for b4signals.com / https://b4indicators.com/threads/spy-swing-strategy.137/

//@version=5
strategy("SPY Swing Strategy", overlay=true, initial_capital=1000)

initialBalance = strategy.initial_capital
atrPeriods = input.int(10, "ATR Periods")
lowest_close = input.int(3, "Lowest Close")
trend_average = input.int(66, "Trend Average")
highest_close = input.int(19, "Highest Close")
stop_var = input.float(7.95, "Stop Var")
targetWinRate = input.float(1, "Target Win Rate")
targetWinLoss = input.float(.50, "Target Win/Loss")
useMoneyManagement = input.bool(true, "Use Money Management")
intradayOnly = input.bool(false, "Intraday Only")

FPL = strategy.grossprofit
entry = strategy.opentrades.entry_price(strategy.opentrades - 1)

isTrade = not intradayOnly

atrA = ta.sma(math.abs(close - close[1]), atrPeriods)
atr = atrA < 1 ? 1 : atrA

portfolioSize = not na(FPL) ? FPL + initialBalance : initialBalance
contractsToTrade = useMoneyManagement ? math.floor(portfolioSize / (atr * close)) : 1

buyCond = close <= ta.lowest(close, lowest_close) and close > ta.sma(close, trend_average)
sellCond = close >= ta.highest(close, highest_close)

direction = 0
direction := bar_index == 1 ? 0 :
     direction[1] == 0 and buyCond and contractsToTrade > 0 ? 1 :
     direction[1] == 1 and sellCond ? 0 :
     direction[1]

stop_price = close
stop_price := ta.cross(direction, 0) ? close - (stop_var * atr) : stop_price[1]

plotshape(direction == 1 and direction != direction[1], title="Buy Signal", text="Buy", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.black, size=size.normal)
plotshape(direction == 0 and direction != direction[1], title="Exit Signal", text="Exit", style=shape.labeldown, location=location.abovebar, color=color.gray, textcolor=color.black, size=size.normal)

var table chartHUD = table.new(position.top_right, 2, 2, bgcolor = color.gray, frame_width = 0)
if barstate.islast
    table.cell(chartHUD, 0, 0, "Direction", bgcolor = color.black , text_color = color.white)
    table.cell(chartHUD, 1, 0, direction == 1 ? "LONG" : "Neutral", bgcolor = direction == 1 ? color.green : color.gray, text_color = direction == 1 ? color.black : color.white)
    table.cell(chartHUD, 0, 1, "Shares To Trade", bgcolor = color.black, text_color = color.white)
    table.cell(chartHUD, 1, 1, direction == 1 ? "n/a" : str.tostring(contractsToTrade), bgcolor = color.gray, text_color = color.white)

strategy.order("LONG", strategy.long, contractsToTrade, when = isTrade and ta.crossover(direction, 0))
strategy.close("LONG", when = not isTrade or ta.crossunder(direction, 1), comment = "EXIT")
 
@workingprogrammer here is the TradingView conversion.

It is published and available here: https://www.tradingview.com/script/KVDjl4y6-SPY-Swing-Strategy/

Code is open but publishing it here too.
Code:
// SPY Swing Strategy / Daily Trader
// Free for use. Header credits must be included when any form of the code included in this package is used.
// v1.0 - barbaros - converted for b4signals.com / https://b4indicators.com/threads/spy-swing-strategy.137/

//@version=5
strategy("SPY Swing Strategy", overlay=true, initial_capital=1000)

initialBalance = strategy.initial_capital
atrPeriods = input.int(10, "ATR Periods")
lowest_close = input.int(3, "Lowest Close")
trend_average = input.int(66, "Trend Average")
highest_close = input.int(19, "Highest Close")
stop_var = input.float(7.95, "Stop Var")
targetWinRate = input.float(1, "Target Win Rate")
targetWinLoss = input.float(.50, "Target Win/Loss")
useMoneyManagement = input.bool(true, "Use Money Management")
intradayOnly = input.bool(false, "Intraday Only")

FPL = strategy.grossprofit
entry = strategy.opentrades.entry_price(strategy.opentrades - 1)

isTrade = not intradayOnly

atrA = ta.sma(math.abs(close - close[1]), atrPeriods)
atr = atrA < 1 ? 1 : atrA

portfolioSize = not na(FPL) ? FPL + initialBalance : initialBalance
contractsToTrade = useMoneyManagement ? math.floor(portfolioSize / (atr * close)) : 1

buyCond = close <= ta.lowest(close, lowest_close) and close > ta.sma(close, trend_average)
sellCond = close >= ta.highest(close, highest_close)

direction = 0
direction := bar_index == 1 ? 0 :
     direction[1] == 0 and buyCond and contractsToTrade > 0 ? 1 :
     direction[1] == 1 and sellCond ? 0 :
     direction[1]

stop_price = close
stop_price := ta.cross(direction, 0) ? close - (stop_var * atr) : stop_price[1]

plotshape(direction == 1 and direction != direction[1], title="Buy Signal", text="Buy", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.black, size=size.normal)
plotshape(direction == 0 and direction != direction[1], title="Exit Signal", text="Exit", style=shape.labeldown, location=location.abovebar, color=color.gray, textcolor=color.black, size=size.normal)

strategy.order("LONG", strategy.long, contractsToTrade, when = isTrade and ta.crossover(direction, 0))
strategy.close("LONG", when = not isTrade or ta.crossunder(direction, 1), comment = "EXIT")
Thank you - appreciate your work and support to the community! I will continue testing this on trading view and TOS and report back with findings
 

barbaros

Administrator
Staff member
Previous script description wasn't liked by TradingView gods and it was removed. Here is the new release.

https://www.tradingview.com/script/fVTO20bS-SPY-Swing-Strategy/

Added the intraday time selection and filter.

Code:
// SPY Swing Strategy / Daily Trader
// Free for use. Header credits must be included when any form of the code included in this package is used.
// v1.0 - barbaros - converted for b4signals.com / https://b4indicators.com/threads/spy-swing-strategy.137/

//@version=5
strategy("SPY Swing Strategy", overlay=true, initial_capital=1000)

initialBalance = strategy.initial_capital
atrPeriods = input.int(10, "ATR Periods")
lowest_close = input.int(3, "Lowest Close")
trend_average = input.int(66, "Trend Average")
highest_close = input.int(19, "Highest Close")
stop_var = input.float(7.95, "Stop Var")
targetWinRate = input.float(1, "Target Win Rate")
targetWinLoss = input.float(.50, "Target Win/Loss")
useMoneyManagement = input.bool(true, "Use Money Management")
intradayOnly = input.bool(false, "Intraday Only")

TimeZone = input.string(title="Timezone", defval="America/New_York", options=["America/New_York", "Exchange"], group="Market Hours")
SessionTime = input.session(title="Session", defval="0930-1600", group="Market Hours")

FPL = strategy.grossprofit
entry = strategy.opentrades.entry_price(strategy.opentrades - 1)

isSession = nz(time(timeframe.period, SessionTime, TimeZone == "Exchange" ? syminfo.timezone : TimeZone)) != 0
isTrade = not intradayOnly or isSession

atrA = ta.sma(math.abs(close - close[1]), atrPeriods)
atr = atrA < 1 ? 1 : atrA

portfolioSize = not na(FPL) ? FPL + initialBalance : initialBalance
contractsToTrade = useMoneyManagement ? math.floor(portfolioSize / (atr * close)) : 1

buyCond = close <= ta.lowest(close, lowest_close) and close > ta.sma(close, trend_average)
sellCond = close >= ta.highest(close, highest_close)

direction = 0
direction := bar_index == 1 ? 0 :
     direction[1] == 0 and buyCond and contractsToTrade > 0 ? 1 :
     direction[1] == 1 and sellCond ? 0 :
     direction[1]

stop_price = close
stop_price := ta.cross(direction, 0) ? close - (stop_var * atr) : stop_price[1]

plotshape(isTrade and direction == 1 and direction != direction[1], title="Buy Signal", text="Buy", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.black, size=size.normal)
plotshape(isTrade and direction == 0 and direction != direction[1], title="Exit Signal", text="Exit", style=shape.labeldown, location=location.abovebar, color=color.gray, textcolor=color.black, size=size.normal)

var table chartHUD = table.new(position.top_right, 2, 2, bgcolor = color.gray, frame_width = 0)
if barstate.islast
    table.cell(chartHUD, 0, 0, "Direction", bgcolor = color.black , text_color = color.white)
    table.cell(chartHUD, 1, 0, direction == 1 ? "LONG" : "Neutral", bgcolor = direction == 1 ? color.green : color.gray, text_color = direction == 1 ? color.black : color.white)
    table.cell(chartHUD, 0, 1, "Shares To Trade", bgcolor = color.black, text_color = color.white)
    table.cell(chartHUD, 1, 1, direction == 1 ? "n/a" : str.tostring(contractsToTrade), bgcolor = color.gray, text_color = color.white)

strategy.order("LONG", strategy.long, contractsToTrade, when = isTrade and ta.crossover(direction, 0))
strategy.close("LONG", when = not isTrade or ta.crossunder(direction, 1), comment = "EXIT")
 

barbaros

Administrator
Staff member
Updated ToS version to add chart bubbles to match TradingView.

Code:
# SPY Daily Trader
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - added intraday option
# v1.2 - barbaros - percent profit calculation fix
# v1.3 - barbaros - added chart bubbles

input initialBalance = 1000;
input atrPeriods = 10;
input lowest_close = 3;
input trend_average = 66;
input highest_close = 19;
input stop_var = 7.95;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;
input intradayOnly = no;
input showBubbles = yes;

def FPL = FloatingPL();
def entry = EntryPrice();

def isTrade = !intradayOnly or (SecondsTillTime(0930) <= 0 and SecondsTillTime(1600) > 0);

def atrA = Average(AbsValue(close - close[1]), atrPeriods);
def atr = if atrA < 1 then 1 else atrA;

def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def contractsToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;

AddLabel(yes, "Shares To Trade: " + contractsToTrade, color.gray);

def buyCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def sellCond = close >= Highest(close, highest_close);

def direction = if BarNumber() == 1 then 0
                else if direction[1] == 0 and  buyCond and contractsToTrade > 0 then 1
                else if direction[1] == 1 and sellCond then 0
                else direction[1];

def stop_price = if BarNumber() == 1 then close else if direction crosses 0 then close - (stop_var * atr) else stop_price[1];

AddChartBubble(isTrade and showBubbles and direction crosses above 0, low, "BUY", Color.GREEN, no);
AddChartBubble(showBubbles and (!isTrade or direction crosses below 1), high, "EXIT", Color.GRAY, yes);

AddOrder(OrderType.BUY_TO_OPEN, isTrade and direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, !isTrade or direction crosses below 1, name = "EXIT");

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else Double.NaN;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else Double.NaN;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.WHITE
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );

AddLabel(yes,
        text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent((portfolioSize / initialBalance) - 1) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
 

NPTechs

New member
Could a reverse logic be applied for Shorts? eg close < 66d average & close highest in 3 days for an entry?
 

barbaros

Administrator
Staff member
Bug fixes for intraday exit bubbles.

Code:
# SPY Daily Trader
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - added intraday option
# v1.2 - barbaros - percent profit calculation fix
# v1.3 - barbaros - added chart bubbles
# v1.4 - barbaros - bug fixes

input initialBalance = 1000;
input atrPeriods = 10;
input lowest_close = 3;
input trend_average = 66;
input highest_close = 19;
input stop_var = 7.95;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;
input intradayOnly = no;
input showBubbles = yes;

def FPL = FloatingPL();
def entry = EntryPrice();

def isTrade = !intradayOnly or (SecondsTillTime(0930) <= 0 and SecondsTillTime(1600) > 0);

def atrA = Average(AbsValue(close - close[1]), atrPeriods);
def atr = if atrA < 1 then 1 else atrA;

def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def contractsToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;

AddLabel(yes, "Shares To Trade: " + contractsToTrade, color.gray);

def buyCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def sellCond = close >= Highest(close, highest_close);

def direction = if BarNumber() == 1 then 0
                else if direction[1] == 0 and  buyCond and contractsToTrade > 0 then 1
                else if direction[1] == 1 and sellCond then 0
                else direction[1];

def stop_price = if BarNumber() == 1 then close else if direction crosses 0 then close - (stop_var * atr) else stop_price[1];

AddChartBubble(isTrade and showBubbles and direction crosses above 0, low, "BUY", Color.GREEN, no);
AddChartBubble(showBubbles and ((isTrade[1] and !isTrade) or (isTrade and direction crosses below 1)), high, "EXIT", Color.GRAY, yes);

AddOrder(OrderType.BUY_TO_OPEN, isTrade and direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, !isTrade or direction crosses below 1, name = "EXIT");

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else Double.NaN;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else Double.NaN;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.WHITE
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );

AddLabel(yes,
        text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent((portfolioSize / initialBalance) - 1) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
 

NPTechs

New member
Bug fixes for intraday exit bubbles.

Code:
# SPY Daily Trader
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - added intraday option
# v1.2 - barbaros - percent profit calculation fix
# v1.3 - barbaros - added chart bubbles
# v1.4 - barbaros - bug fixes

input initialBalance = 1000;
input atrPeriods = 10;
input lowest_close = 3;
input trend_average = 66;
input highest_close = 19;
input stop_var = 7.95;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;
input intradayOnly = no;
input showBubbles = yes;

def FPL = FloatingPL();
def entry = EntryPrice();

def isTrade = !intradayOnly or (SecondsTillTime(0930) <= 0 and SecondsTillTime(1600) > 0);

def atrA = Average(AbsValue(close - close[1]), atrPeriods);
def atr = if atrA < 1 then 1 else atrA;

def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def contractsToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;

AddLabel(yes, "Shares To Trade: " + contractsToTrade, color.gray);

def buyCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def sellCond = close >= Highest(close, highest_close);

def direction = if BarNumber() == 1 then 0
                else if direction[1] == 0 and  buyCond and contractsToTrade > 0 then 1
                else if direction[1] == 1 and sellCond then 0
                else direction[1];

def stop_price = if BarNumber() == 1 then close else if direction crosses 0 then close - (stop_var * atr) else stop_price[1];

AddChartBubble(isTrade and showBubbles and direction crosses above 0, low, "BUY", Color.GREEN, no);
AddChartBubble(showBubbles and ((isTrade[1] and !isTrade) or (isTrade and direction crosses below 1)), high, "EXIT", Color.GRAY, yes);

AddOrder(OrderType.BUY_TO_OPEN, isTrade and direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, !isTrade or direction crosses below 1, name = "EXIT");

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else Double.NaN;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else Double.NaN;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.WHITE
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );

AddLabel(yes,
        text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent((portfolioSize / initialBalance) - 1) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
@barbaros thanks.. Occasionally, an Exit label is seen (after market opens) without a prior Buy or Long, this was in v1.3 as well.
 

NPTechs

New member
uc

ES-3m-Jan31-CST

uc

ES-3m-Feb02-CST

uc

ES-3m-Feb03-CST
 

barbaros

Administrator
Staff member
uc

ES-3m-Jan31-CST

uc

ES-3m-Feb02-CST

uc

ES-3m-Feb03-CST
Got it....this seems to happen because the script is still holding those positions and not showing the labels.

Here is v1.5, hopefully fixes it.
Code:
# SPY Daily Trader
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - added intraday option
# v1.2 - barbaros - percent profit calculation fix
# v1.3 - barbaros - added chart bubbles
# v1.4 - barbaros - bug fixes
# v1.5 - barbaros - more bug fixes

input initialBalance = 1000;
input atrPeriods = 10;
input lowest_close = 3;
input trend_average = 66;
input highest_close = 19;
input stop_var = 7.95;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;
input intradayOnly = no;
input showBubbles = yes;

def FPL = FloatingPL();
def entry = EntryPrice();

def isTrade = !intradayOnly or (SecondsTillTime(0930) <= 0 and SecondsTillTime(1600) > 0);

def atrA = Average(AbsValue(close - close[1]), atrPeriods);
def atr = if atrA < 1 then 1 else atrA;

def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def contractsToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;

AddLabel(yes, "Shares To Trade: " + contractsToTrade, color.gray);

def buyCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def sellCond = close >= Highest(close, highest_close);

def direction = if BarNumber() == 1 or (isTrade[1] and !isTrade) then 0
                else if isTrade and direction[1] == 0 and  buyCond and contractsToTrade > 0 then 1
                else if isTrade and direction[1] == 1 and sellCond then 0
                else direction[1];

def stop_price = if BarNumber() == 1 then close else if direction crosses 0 then close - (stop_var * atr) else stop_price[1];

AddChartBubble(showBubbles and direction crosses above 0, low, "BUY", Color.GREEN, no);
AddChartBubble(showBubbles and direction crosses below 1, high, "EXIT", Color.GRAY, yes);

AddOrder(OrderType.BUY_TO_OPEN, isTrade and direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, !isTrade or direction crosses below 1, name = "EXIT");

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else Double.NaN;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else Double.NaN;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.WHITE
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );

AddLabel(yes,
        text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent((portfolioSize / initialBalance) - 1) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
 

NPTechs

New member
Got it....this seems to happen because the script is still holding those positions and not showing the labels.

Here is v1.5, hopefully fixes it.
Code:
# SPY Daily Trader
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - added intraday option
# v1.2 - barbaros - percent profit calculation fix
# v1.3 - barbaros - added chart bubbles
# v1.4 - barbaros - bug fixes
# v1.5 - barbaros - more bug fixes

input initialBalance = 1000;
input atrPeriods = 10;
input lowest_close = 3;
input trend_average = 66;
input highest_close = 19;
input stop_var = 7.95;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;
input intradayOnly = no;
input showBubbles = yes;

def FPL = FloatingPL();
def entry = EntryPrice();

def isTrade = !intradayOnly or (SecondsTillTime(0930) <= 0 and SecondsTillTime(1600) > 0);

def atrA = Average(AbsValue(close - close[1]), atrPeriods);
def atr = if atrA < 1 then 1 else atrA;

def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def contractsToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;

AddLabel(yes, "Shares To Trade: " + contractsToTrade, color.gray);

def buyCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def sellCond = close >= Highest(close, highest_close);

def direction = if BarNumber() == 1 or (isTrade[1] and !isTrade) then 0
                else if isTrade and direction[1] == 0 and  buyCond and contractsToTrade > 0 then 1
                else if isTrade and direction[1] == 1 and sellCond then 0
                else direction[1];

def stop_price = if BarNumber() == 1 then close else if direction crosses 0 then close - (stop_var * atr) else stop_price[1];

AddChartBubble(showBubbles and direction crosses above 0, low, "BUY", Color.GREEN, no);
AddChartBubble(showBubbles and direction crosses below 1, high, "EXIT", Color.GRAY, yes);

AddOrder(OrderType.BUY_TO_OPEN, isTrade and direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, !isTrade or direction crosses below 1, name = "EXIT");

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else Double.NaN;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else Double.NaN;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.WHITE
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );

AddLabel(yes,
        text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent((portfolioSize / initialBalance) - 1) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
Looks good.. Thanks.
 

NPTechs

New member
When I copy this code in think swim I the triangle warning sign, it saves, but when I add it to the chart I don't get anything. If there a debugging tool I can use to see if I have some sort of whitespace on the copy. I copied it multiple times. Thanks
Save it as a strategy, not study.

uc
 
Top