VixFix Swing Trading (aka Buy the Dip)

barbaros

Administrator
Staff member
Thinkscript implementation of Flash Crash Trading Strategy from https://relaxedtrader.com/flash-crash-trading-strategy/

Strategy utilizes synthetic VIX for detecting fear with filtering out trades using a moving average. 81% win-rate is confirmed with SPY.

Original author's statistics:
eRrrkOz.png


Original author's equity curve with ES:
PQhbCYn.png


Converted Thinkscript performance:
DaNL3Bf.png


Converted Thinkscript with few tweaks:
Code:
# Flash Crash - Buy the Dip Strategy
# 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

input movingAverage = 170;
input vixFixBuy = 4;
input vixFixSell = 2;
input atrPeriods = 10;
input initialBalance = 1000;
input targetWinRate = 1;
input targetWinLoss = .50;
input useMoneyManagement = yes;

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

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 vix_fix = ((Highest(close, 21) - low) / Highest(close, 21)) * 100;
def buyCond = vix_fix > vixFixBuy and close >= Average(close, movingAverage);
def sellCond = vix_fix <= vixFixSell;

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];

AddOrder(OrderType.BUY_TO_OPEN, direction crosses above 0, tradeSize = contractsToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, 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) + ")  ",
        color = if portfolioSize > initialBalance
                then Color.CYAN
                else Color.MAGENTA
    );
 

anasmatar

New member
Thanks @barbaros .. I am not a coder but could i ask if the code above can be plugged when viewing/trading SPY to give a signal based on VIX pre-set threshold?
 

barbaros

Administrator
Staff member
Thanks @barbaros .. I am not a coder but could i ask if the code above can be plugged when viewing/trading SPY to give a signal based on VIX pre-set threshold?
Two options, vixFixBuy and vixFixSell, are the ones to tweak for Vix thresholds. Is this what you were looking for?
 

anasmatar

New member
The idea is that when VIX hits the historical threshold (>38) then the fear gauge is at its max, volatility is high, and panic selling pressure is high then one is to take advantage to ride the wave of shorting the index. How does this sound?
How do I tweak the VixFixBuy or sell

Thanks Barbaros
 

barbaros

Administrator
Staff member
The idea is that when VIX hits the historical threshold (>38) then the fear gauge is at its max, volatility is high, and panic selling pressure is high then one is to take advantage to ride the wave of shorting the index. How does this sound?
How do I tweak the VixFixBuy or sell

Thanks Barbaros
Sounds good. Are you asking not to include the rest of the strategy but just use VixFix? The current strategy is for longs only. We can make a new one for shorting.
 

anasmatar

New member
I copied the above code over SPY and SPX but there were no signals whatsoever generated as per the shown image above.. when it is supposed to fire?
I appreciate if you can make it fire both ways (go long and go short) with configurable VIX thresholds (what is the VixBuy 4 and VixSell at 2 means in the code?)
 

anasmatar

New member
YTD, only 2 trades were taken ! .. there should be a way to customize the thresholds (i don't know how) otherwise, it's not an effective strategy as there were plenty of opportunities to short the market
 

barbaros

Administrator
Staff member
YTD, only 2 trades were taken ! .. there should be a way to customize the thresholds (i don't know how) otherwise, it's not an effective strategy as there were plenty of opportunities to short the market
I'm not the original author of this strategy. There are a few parameters you can customize, moving average length, atr length, and vixfix limits. Also, market has been downtrending this year. Taking longs is not too desirable unless you can pinpoint the bottoms for retracements.
 

anasmatar

New member
I agree, the idea is to short the market once VIX hits 34 or above
I don't understand what VixBuy 4 and VixSell at 2, if you can explain - i may find a way to alter these parameters.
Thanks!
 

barbaros

Administrator
Staff member
I agree, the idea is to short the market once VIX hits 34 or above
I don't understand what VixBuy 4 and VixSell at 2, if you can explain - i may find a way to alter these parameters.
Thanks!
We'll need to make a new strategy with it. Not a big deal, we can make it happen.

VixBuy is entry value, and VixSell is the exit value for the long side.
 
Top