- Si el cierre está por encima de una media de 200 entonces estamos alcistas
- Si estamos alcistas y el RSI(2) cae por debajo de 30 compramos
- Si estamos comprados y el cierre supera una media de 10 sesiones cerramos los largos
- El sistema es solo largo y hay un stop loss de 6 desviaciones estándar
Debajo vemos que esta lógica funciona muy bien en los índices, que por su naturaleza tienen un comportamiento de reversión a la media (comprar cuando caen). Debajo vemos el Nasdaq100 pero en general este sistema va bien en cualquier índice:
Cuando lo probamos en el futuro mini del SP500 vemos que funciona muy bien. Debajo se puede ver la curva de capital en el SP500 desde el año 2000 y descontando $100 por operación en concepto de comisiones y deslizamiento. Los parámetros que vimos en la descripción del sistema son optimizables. En esta curva de capital del SP500 los parámetros utilizados han sido: 250 para la media de largo plazo, 26 para el umbral de compra y 8 para la media de salir de los largos.
El sistema ha generado unas 300 operaciones en el periodo con un 78% de aciertos. La relación entre ganancia y drawdown es superior a 8 y tiene unos ratios muy buenos como un Sharpe de 1.40. Podríamos decir que se trata de un buen sistema de trading.
Como viene siendo habitual el código de debajo incluye la gestión del dimensionamiento mediante un modelo de Carver para un objetivo de volatilidad anual. El fichero include <futuros.afl> contiene los multiplicadores de los futuros y se puede encontrar en este blog.
CÓDIGO DEL SISTEMA
//-------------------------------------------------------
// SISTEMA CONNORS RSI2
// OSCAR G. CAGIGAS
// 10 ABRIL 2018
//-------------------------------------------------------
//VARIABLES OPTIMIZABLES//
nstop = 6;//Optimize("nstop",5,4,6,1);
med = Optimize("med",250,200,600,50);
umbral = Optimize("umbral",26,4,30,2);
med2 = Optimize("med2",8,4,12,1);
//----------------------------------------------------------------
//PESO EN LA CARTERA//
iw = 0.2;
//PARAMETROS DE GESTION DE CAPITAL
Eq = 100000;
tavol = 0.3;
idm = 2;
//CAPITAL INICIAL Y COMISIONES//
SetOption( "initialequity", 100000 ); // starting capital
SetOption("PriceBoundChecking",1);
SetOption("CommissionMode", 2);
SetOption("commissionamount",50); //COMISIÓN INDIVIDUAL (ENTRADA O SALIDA)
SetOption("WarningLevel", 1 );
//DIMENSIONAMIENTO//
#include <futuros.afl>
SetOption("maxopenpositions",4);
//DESVIACION STANDARD EXPONENCIAL
desv_carver = sqrt( EMA( ( C-Ref(C,-1) )^2, 36 ) ) ;
//----NÚMERO DE FUTUROS EN BASE AL FORECAST ANTERIOR, VOLATILIDAD Y EQUITY----
dvt = Eq * tavol / 16; //daily volatility target
ivv = desv_carver * PointValue; //instrument value volatility
vs = Nz(dvt / ivv); //volatility scalar
pos = vs * iw * idm; //forecast de 10 siempre
numfut = round(pos); //el número de contratos
MarginDeposit = 1; PositionSize = NumFut;
//----------------------------------------------------------
//mostrar indicadores//
pintarRSI=ParamToggle("Pintar RSI", "No|Yes", 0);
pintarMed=ParamToggle("Pintar Media", "No|Yes", 0);
//DEFINICIONES//
alcista = C > MA(C,med);
//ENTRY//
Buy = setupa = alcista AND RSI(2) < umbral;
//EXIT//
Sell = C > MA(C,med2);
//PANIC STOP//
STOP=Nz(nstop * desv_carver);
ApplyStop(stopTypeLoss,stopModePoint, STOP,1,0);
Equity(1,0);
//remove excesive signals//
Buy=ExRem(Buy,Sell);
Sell=ExRem(Sell,Buy);
//LONG ONLY//
Short=Cover=0;
//largo o corto//
largo=Flip(Buy,Sell OR Short);
corto=Flip(Short,Cover OR Buy);
//SALIDA GRAFICA//
Color = IIf(setupa,colorGreen,colorlightBlue);
Plot(C,"PRICE",Color,styleBar|styleThick,Null,Null,0,0,1);
PlotShapes(IIf(Buy,shapeUpArrow,shapeNone),colorGreen,0,L,-15);
PlotShapes(IIf(Buy,shapeHollowCircle,shapeNone),colorGreen,0,BuyPrice,0);
PlotShapes(IIf(Sell AND NOT Corto,shapeDownArrow,shapeNone),colorRed,0,H,-15);
PlotShapes(IIf(Sell AND NOT Corto,shapeHollowCircle,shapeNone),colorRed,0,SellPrice,0);
PlotShapes(IIf(Short,shapeDownArrow,shapeNone),colorBrown,0,H,-15);
PlotShapes(IIf(Short,shapeHollowCircle,shapeNone),colorBrown,0,ShortPrice,0);
PlotShapes(IIf(Cover AND NOT Largo,shapeUpArrow,shapeNone),colorDarkGreen,0,L,-15);
PlotShapes(IIf(Cover AND NOT Largo,shapeHollowCircle,shapeNone),colorDarkGreen,0,CoverPrice,0);
if (pintarRSI)
{
Plot(RSI(2),"RSI(2)",colorBlue,styleThick|styleLeftAxisScale);
Plot(umbral,"Umbral",colorBlack,styleLine|styleLeftAxisScale);
Plot(400,"",colorAqua,styleNoDraw|styleLeftAxisScale);
}
if (pintarMed)
{
Plot(MA(C,med),"MA(" + med + ")",colorBlue,styleThick);
Plot(MA(C,med2),"MA(" + med2 + ")",colorRed,styleThick);
}
//PLOTTEXT//
dist = 2*ATR(10);
for( i = 0; i < BarCount; i++ )
{
if( Buy[i] ) PlotText( "Long "+NumToStr(ValueWhen(Buy[i],BuyPrice[i]),1.2), i, L[ i ]-dist[i], colorGreen );
if( Sell[i] AND NOT Short[i]) PlotText( "Exit " + NumToStr(ValueWhen(Sell[i],SellPrice[i]),1.2), i, H[ i ]+dist[i], colorRed );
if( Short[i] ) PlotText( "Short "+NumToStr(ValueWhen(Short[i],ShortPrice[i]),1.2), i, H[ i ]+dist[i], colorBrown );
if( Cover[i] AND NOT Buy[i]) PlotText( "Cover " + NumToStr(ValueWhen(Cover[i],CoverPrice[i]),1.2), i, L[ i ]-dist[i], colorBlack );
}
//CHART//
Sellstop = ValueWhen(Buy,BuyPrice-STOP);
color = IIf(numfut == 0, colorLavender, 0);
SetChartOptions(0,chartShowDates);
Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) )
+"\n"+ FullName()+"\n"+EncodeColor(colorBlue)+"SIST CONNORS RSI2"
+"\n"+EncodeColor(colorGrey40)+"STDEV = "+WriteVal(desv_carver,1.6)+" Pts ; x" + WriteVal(PointValue,1.0)
+"\n"+EncodeColor(colorRed)+"VOLAT = $"+WriteVal(ivv,1.2)
+"\n"+ EncodeColor(colorRed)+"SL = "+NumToStr(sellstop,1.2)
+" ; RISK = "+WriteVal((C-sellstop)*PointValue*NumFut,1.0)
+"\n"+"daily volat target = " + WriteVal(dvt,1.0)
+"\n"+"volat scalar = " + WriteVal(vs,1.2)
+"\n"+"inst weight = " + WriteVal(100*iw,1.0) +" %"
+"\n"+"ins div mul = " + WriteVal(idm,1.2)
+"\n"+"pos = " + WriteVal(pos,1.2)
+"\n"+EncodeColor(colorBlue)+"NumFut = " + WriteVal(numfut,1.0);
//PINTAMOS EL STOP//
stopline = IIf(largo OR Buy OR sell, ValueWhen(Buy, buyprice-stop), Null);
Plot(stopline, "SL", colorRed,styleDashed);
GfxSetOverlayMode(1);
GfxSelectFont("Tahoma", Status("pxheight")/30 );
GfxSetTextAlign( 6 );// center alignment
GfxSetTextColor( ColorRGB( 200, 200, 200 ) );
GfxSetBkMode(1); // transparent
GfxTextOut( "CRSI2", Status("pxwidth")/10, Status("pxheight")/2.6 );
Hola,
ResponderEliminarUna observación: ¿Qué ocurre cuando RSI(2) cae por debajo de 30 pero el precio está por encima de la media de 10? ¿Compramos? ¿Esperamos a que el precio esté por debajo de la media?
Saludos y feliz 2020
Buena pregunta :) Todo depende de cómo lo hayas programado. En un principio esto no ocurrirá mucho, pero si lo quieres tener en cuenta entonces tienes que añadir AND C < MA(C,med2) en la compra para que solo compre si estamos por debajo. En el código no está incluido pero se puede añadir. Tal cual está ahora la posición se cerraría justo después de abrirla. No he revisado una a una las operaciones para ver si esto ocurre con la suficiente frecuencia como para que sea un problema, pero en cualquier caso tienes razón y el código estará más correcto si añadimos esto.
Eliminar