Staggered entry if SPX is x% below all-time high

Hi,

please coulld anyone help me to code the following trading strategy:

**Strategy Definition

  • Signal Generator: SPX (S&P 500 Index)

  • Traded Asset: QQQ

  • **Entry Rules

    • 20% below SPX all-time high → enter with 50% position
    • 30% below SPX all-time high → add another 25%
    • 40% below SPX all-time high → add the remaining 25%
  • **Exit Rule: Exit on the next day when SPX reaches a new all-time high

  • **No Rebalancing

  • **Backtest is run on QQQ, but signals are generated from SPX

i did a copy and paste of your question in GROK and it gave a good start. Below some code that works but I think you can do it also just use arrays. Maybe will try that later. Chart shows SPY. If you then put QQQ in the chart it uses the signals of SPY.

Code is a starting point. Actually you also need to check for multiple entry signals in the same bar. I did not do that because chances that it happens is low in the case of SPY

sym = "SPY";

// Set the traded asset to QQQ
SetForeign( sym ); // Use sym for signal generation

// Calculate All-Time High of sym
spxClose = C;
spxATH = Highest( spxClose );

// Calculate percentage drop from ATH
percentDrop = ( spxATH - spxClose ) / spxATH * 100;

// Define entry signals
entry20 = Cross( percentDrop, 20 );
entry30 = Cross( percentDrop, 30 );
entry40 = Cross( percentDrop, 40 );

// Define exit signal: SPX reaches new all-time high
isNewATH = Cross( spxClose, Ref( spxATH, -1 ) );

// Restore price arrays to QQQ
RestorePriceArrays();

posSize = 0;
buyType = 0;
Buy = Sell = 0;
BuyPrice = SellPrice = 0;
in20 = in30 = in40 = 0;
inlong = 0;

// Generate buy signals based on SPX drop levels
for( i = 0; i < BarCount; i++ )
{
    if( isNewATH[i] AND inlong == 1 )
    {
        Sell[i] = 1;
        SellPrice[i] = C[i];
        in20 = in30 = in40 = 0;
        inlong = 0;
    }
    else
        if( entry20[i] AND in20 == 0 )
        {
            // 20% drop: 50% position
            Buy[i] = 1;
            BuyPrice[i] = C[i];
            buyType[i] = 20;
            posSize[i] = 50;
            in20 = 1;
            inlong = 1;
        }
        else
            if( entry30[i] AND in30 == 0 )
            {
                // 30% drop: Add 25% (total 75%)
                Buy[i] = sigScaleIn;
                BuyPrice[i] = C[i];
                buyType[i] = 30;
                posSize[i] = 25;
                in30 = 1;
                inlong = 1;
            }
            else
                if( entry40[i] AND in40 == 0 )
                {
                    // 40% drop: Add 25% (total 100%)
                    Buy[i] = sigScaleIn;
                    BuyPrice[i] = C[i];
                    buyType[i] = 40;
                    posSize[i] = 25;
                    in40 = 1;
                    inlong = 1;
                }
}

SetPositionSize( posSize, spsPercentOfEquity );
SetTradeDelays( 0, 0, 0, 0 );
SetOption( "CommissionMode", 3 );
SetOption( "CommissionAmount", 0.005 );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );

if( Name() == sym )
    Plot( spxATH, "", colorAqua, styleLine, Null, Null, 0, 0, 1 );

PlotShapes( IIf( BuyType == 20, shapeSmallUpTriangle, shapeNone ), colorAqua, 0, L, -20 );
PlotShapes( IIf( BuyType == 30, shapeSmallUpTriangle, shapeNone ), colorYellow, 0, L, -20 );
PlotShapes( IIf( BuyType == 40, shapeSmallUpTriangle, shapeNone ), colorPink, 0, L, -20 );
PlotShapes( IIf( Buy, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Sell, shapeSmallDownTriangle, shapeNone ), colorRed, 0, H, -20 );
PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorWhite, 0, SellPrice, 0 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

for( i = fvb; i <= lvb; i++ )
{
    if( BuyType[i] == 20 )
        PlotTextSetFont( "20%", "Arial Bold", 10, i, L[i], colorAqua, colorDefault, -40 );

    if( BuyType[i] == 30 )
        PlotTextSetFont( "30%", "Arial Bold", 10, i, L[i], colorYellow, colorDefault, -40 );

    if( BuyType[i] == 40 )
        PlotTextSetFont( "40%", "Arial Bold", 10, i, L[i], colorPink, colorDefault, -40 );
}


1 Like

Thank you for sharing the code.
I manually checked the backtest results (the individual trades) and fortunately, the trades do indeed seem to be correct.
Thanks again.