miércoles, 28 de noviembre de 2018

EL SISTEMA MERSI PARA COMMODITIES

Las entradas anteriores del Blog han preparado el terreno para los sistemas de trading. Nos han permitido cargar Amibroker con la lista de los mercados más líquidos de materias primas y que este lea correctamente los multiplicadores. Adicionalmente hemos definido el número de contratos para un objetivo de volatilidad determinada (modelo de Robert Carver).

Pues bien...

Ha llegado el momento de presentar los sistemas de Trading!

El primero va a ser el sistema de reversión a la media con RSI también denominado "MERSI COMMODITIES". Las reglas son bien simples:


·      Estamos alcistas si el cierre está por encima de una media móvil simple
·      Si estamos alcistas y un RSI cae por debajo de 30 entonces compramos
·      Una vez comprados si el RSI sube por encima de 70 cerramos los largos
·      El sistema es simétrico para las posiciones cortas
·      Hay un stop loss de 6 desviaciones estándar

Qué hacer con este sistema, qué estadísticas tiene, qué ratio de optimización le viene bien... todas estas preguntas han sido contestadas en los informes de Onda4.





*********CÓDIGO DEL SISTEMA MERSI COMMODITIES**************

//---------------------------------------// 
// SISTEMA MERSI COMMODITIES 
// MEAN REVERSION RSI
// OSCAR G. CAGIGAS 
// 28 NOVIEMBRE 2018
//---------------------------------------// 

//PARAMETROS OPTIMIZABLES//
OptimizerSetEngine("spso"); //activar motor de optimización de partículas
RSILength = Optimize("RSI length",9,4,12,1);
MALength = Optimize("MA length",45,40,120,5);
RSIBuyLevel = RSICoverLevel = 30; //Optimize("RSI Low",30,5,50,5);
RSIShortLevel = RSISellLevel  = 70; //Optimize("RSI High",80,50,90,5);
nstop = 6; //Optimize("STOP",9,3,10,1)*ATR(20);

//----------------MONEY MANAGEMENT------------------------------------------

//PESO EN LA CARTERA DE CADA POSICIÓN//   
iw = 0.25;  //instrument weith, 4 posiciones con 25% de peso cada una

//PARAMETROS DE GESTION DE CAPITAL (actualizar)
Eq = 100000; //capital o Equity, actualizar
tavol = 0.20;  //target volatility (20% objetivo anual de volatilidad)
idm = 2; //instrument diversification multiplier

//CAPITAL INICIAL Y COMISIONES//  
SetOption( "initialequity", 100000 ); // starting capital     
SetOption("PriceBoundChecking",1);  
SetOption("CommissionMode", 2);  
SetOption("commissionamount",50);  //COMISIÓN INDIVIDUAL (ENTRADA + SALIDA)  
SetOption("WarningLevel", 1 );   
  
//DIMENSIONAMIENTO//   
#include <futuros.afl>   
SetOption("maxopenpositions",6);  //máximo 6 posiciones simultáneas
decim = 1 + dec/10; //decimales correctos en formato 1.X (dec son los decimales del include futuros)
    
//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;    

//***********SISTEMA DE TRADING****************************************

//FILTRO DE TENDENCIA CON MEDIA//
alcista = C > MA( C, MALength ); //alcista si el cierre está por encima de la media

//OSCILADOR//
osc = RSI( RSILength );

//LONG ENTRY// 
Buy = setupa = osc < RSIBuyLevel AND alcista; 

//LONG EXIT//
Sell = osc > RSISellLevel;

//SHORT ENTRY//
Short = setupb = osc > RSIShortLevel AND !alcista;

//SHORT EXIT//
Cover = osc < RSICoverLevel;

//LARGO o CORTO// 
largo=Flip(Buy,Sell OR Short); 
Corto=Flip(Short,Cover OR Buy);  

//STOP LOSS// 
stop = Nz(nstop * desv_carver);   
ApplyStop(stopTypeLoss,stopModePoint,stop,1,0); //salida inmediata intradiaria al nivel del stop
Equity(1,0); 


//-----------PARTE VISUAL-------------------------------------


//CIRCULOS EN LAS ENTRADAS Y SALIDAS//
Color = IIf(setupa OR setupb ,colorOrange, ColorRGB(30,140,250)); //naranja en las entradas
Plot(C,"PRICE",color,styleBar|styleThick,Null,Null,0,0,2);
PlotShapes(IIf(Buy,shapeUpArrow,shapeNone),colorGreen,0,L,-15);
PlotShapes(IIf(Buy,shapeHollowCircle,shapeNone),colorGreen,0,BuyPrice,0);
PlotShapes(IIf(Sell,shapeDownArrow,shapeNone),colorRed,0,H,-15);
PlotShapes(IIf(Sell,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 Buy,shapeUpArrow,shapeNone),colorDarkGreen,0,L,-15);
PlotShapes(IIf(Cover AND NOT Buy,shapeHollowCircle,shapeNone),colorDarkGreen,0,CoverPrice,0);

//PINTAR LA MEDIA
Plot(MA(C,MAlength), "MA(" +  MAlength + ")",colorRed,styleLine);

//PINTAR EL RSI EN LA PARTE BAJA DEL GRÁFICO
indicador=ParamToggle("Mostrar Indicador", "No|Yes", 0);
if (indicador)
{
Plot(RSI(RSILength),"RSI("+RSILength+")",colorRed,styleThick|styleLeftAxisScale);
Plot(RSIBuyLevel,"SC",colorBlue,styleThick|styleLeftAxisScale);
Plot(RSISellLevel,"SV",colorBlue,styleThick|styleLeftAxisScale);
Plot(300,"",colorBlue,styleLeftAxisScale|styleNoDraw); //para que quede todo abajo
}

//PRECIOS DE STOP LOSS
Sellstop = ValueWhen(Buy,BuyPrice-nstop*desv_carver);
Coverstop = ValueWhen(Short,ShortPrice+nstop*desv_carver);

//CHART//
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)+"SISTEMA MERSI COMMODITIES"
+"\n"+EncodeColor(colorGrey40)+"DESV = "+WriteVal(desv_carver,1.4)+" Pts ; " 
+"$" + WriteVal(NumFut*PointValue*desv_carver,1.0)+" ; N = "+WriteVal(numfut,1.0) + EncodeColor(colorRed) 
+"\n"+"Stop = "+WriteIf(Largo, NumToStr(Sellstop,decim),"")+WriteIf(Corto, NumToStr(Coverstop,decim),"") 
+" ; RISK = "+WriteVal(IIf(largo, C-sellstop,coverstop-c)*PointValue*NumFut,1.0)
+"\n"+ WriteIf(alcista,EncodeColor(colorGreen)+"Alcista",EncodeColor(colorRed)+"Bajista");

//PRECIO EN LAS SEÑALES DE ENTRADA Y SALIDA//
dist = ATR(10); 
for( i = 0; i < BarCount; i++ ) 
if( Buy[i] ) PlotText( "Long "+NumToStr(ValueWhen(Buy[i],BuyPrice[i]),decim), i, L[ i ]-dist[i], colorGreen ); 
if( Sell[i] ) PlotText( "Exit " + NumToStr(ValueWhen(Sell[i],SellPrice[i]),decim), i, H[ i ]+dist[i], colorRed ); 
if( Short[i] ) PlotText( "Short "+NumToStr(ValueWhen(Short[i],ShortPrice[i]),decim), i, L[ i ]-dist[i], colorBrown ); 
if( Cover[i] ) PlotText( "Cover " + NumToStr(ValueWhen(Cover[i],CoverPrice[i]),decim), i, H[ i ]+dist[i], colorBlack ); 
}

9 comentarios:

  1. Buenas Óscar
    He probado el sistema cargando data de tradestation y no me funciona.
    No me cuadran dos aspectos:
    1. El primero que no pones ni buyprice, ni shortprice.
    2. El segundo creo que al usar en la función Applystop, al final el parámetro 0, no funciona el stop en intradía

    ResponderEliminar
    Respuestas
    1. Hola Amador. El sistema está correcto. En Amibroker los arrays BuyPrice y ShortPrice vienen cargados por defecto con el valor del cierre de la barra. Puesto que este sistema opera al cierre no hace falta especificarlo. Si no te aparecen operaciones puede ser por varias razones pero las más comunes son problemas con los multiplicadores o con el PositionSize. Espero que lo soluciones. Saludos.

      Eliminar
  2. Buenos Días Oscar,
    Yo utilizo prorealtime para programación, y opero con acciones. El sistema me parece interesante y queria consultarte 2 cuestiones:
    1) podria aplicarse con cierto exito en acciones?
    2) que configuracion recomendarias para el RSi?

    Gracias Oscar.

    ResponderEliminar
    Respuestas
    1. Solo hay una forma de saberlo, y es aplicarlo a una cartera de acciones y ver los resultados del Backtest. En principio creo que sí que podría aplicarse pues la lógica es universal, no tienen que ser futuros. La optimización con la cartera de acciones nos daría el mejor valor para el periodo del RSI. Saludos

      Eliminar
  3. En el sistema que pones, la configuración del RSI es 9 no?.
    Gracias por la contestación.

    ResponderEliminar
  4. Óscar, el error En el dimensionamiento decim=1 + dec/10;
    Me dice error 29. Variable "dec" used without having been initialized
    Comentas decimales correctos en formato 1.x
    pero no sé qué significa y como solucionarlo.
    Saludos
    Luis

    ResponderEliminar
    Respuestas
    1. https://onda4com.blogspot.com/2018/09/los-multiplicadores-de-los-futuros.html

      En este enlace tienes el fichero include que contiene los multiplicadores, el valor del tick y el número de decimales.

      Vamos a suponer que son 2 (p.e. el SP500). Entonces la dec = 2 y decim = 1 + dec/10 = 1.2 que es el formato que usa Amibroker para presentar un precio con 2 decimales. Así podemos poner cada mercado en el formato más adecuado. Saludos,

      Eliminar
  5. Gracias Óscar. Un saludo
    Luis Enrique

    ResponderEliminar

ENTRADAS POPULARES