# 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
# BETA - barbaros - don't use
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 longCond = close <= Lowest(close, lowest_close) and close > Average(close, trend_average);
def longExitCond = close >= Highest(close, highest_close);
def shortCond = close >= Highest(close, lowest_close) and close < Average(close, trend_average);
def shortExitCond = close <= Lowest(close, highest_close);
def direction = if BarNumber() == 1 or (isTrade[1] and !isTrade) then 0
else if isTrade and direction[1] == 0 and longCond and contractsToTrade > 0 then 1
else if isTrade and direction[1] == 0 and shortCond and contractsToTrade > 0 then -1
else if isTrade and direction[1] == 1 and longExitCond then 0
else if isTrade and direction[1] == -1 and shortExitCond 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, "LONG", 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
);