viernes, 3 de enero de 2020

CALENDAR SPREADS CON FUTUROS (AMIBROKER)

Hoy presentamos un código que calcula y dibuja los spread de calendario entre futuros. Un spread de calendario es una posición contraria entre dos vencimientos de futuros del mismo mercado, por ejemplo el Crudo de Febrero comprado y el Crudo de Marzo vendido en corto. Estas posiciones requieren muy pocas garantías por estar cubiertas, y son muy populares entre algunos operadores.

El código es genérico, así que puede utilizarse en varios mercados (Crudo, Oro, Soja, Magro, Maíz, Bonos, Eurodólar, Gas Natural y hasta futuros del VIX):


La programación tiene en cuenta los códigos de los vencimientos de futuros (F para enero, G para febrero, etc) de forma automática, así que facilita mucho la construcción de spreads.

Asimismo incluye una lógica de reversión a la media con sistema de trading por si se desea operar siguiendo esta estrategia. La forma de sustituir esta estrategia por otra (p.e. tendencial) es cambiando las señales de entrada y salida que se hacen en base al precio diferencia o spread. Los cambios son sencillos.






El sistema utiliza los tickers de IQFeed. Por ejemplo, para el Crudo de Febrero y Marzo (respectivamente) serían los siguientes:


Si vd utiliza otro proveedor de datos debe adaptarlos a la nomenclatura de su proveedor.

CÓDIGO DEL CALENDAR SPREAD

//-------------------------------- 
// CALENDAR SPREAD  
// Oscar G. Cagigas  
// 3 ENERO 2020      
//---------------------------------

mercado = ParamList("MERCADO","CRUDO|ORO|SOJA|MAGRO|MAIZ|BONOS|EURO|GAS|VIX",0);
mo2 = ParamList("MES CERCANO","ENERO|FEBRERO|MARZO|ABRIL|MAYO|JUNIO|JULIO|AGOSTO|SEPTIEMBRE|OCTUBRE|NOVIEMBRE|DICIEMBRE",0);
mo1 = ParamList("MES LEJANO","ENERO|FEBRERO|MARZO|ABRIL|MAYO|JUNIO|JULIO|AGOSTO|SEPTIEMBRE|OCTUBRE|NOVIEMBRE|DICIEMBRE",0);
anyo = 20; //CAMBIAR CADA AÑO

symbol1 = symbol2 = ""; //DEFINICION SIMBOLOS

// MES1-MES2 (LEJANO-CERCANO) SUELE SER SPREAD POSITIVO
switch (mo1) //MES LEJANO
{
 case "ENERO": mes1="F"; break; 
 case "FEBRERO": mes1="G"; break;
 case "MARZO": mes1="H"; break; 
 case "ABRIL": mes1="J"; break;
 case "MAYO": mes1="K"; break;
 case "JUNIO": mes1="M"; break;
 case "JULIO": mes1="N"; break;
 case "AGOSTO": mes1="Q"; break;
 case "SEPTIEMBRE": mes1="U"; break;
 case "OCTUBRE": mes1="V"; break;
 case "NOVIEMBRE": mes1="X"; break;
 case "DICIEMBRE": mes1="Z"; break;
}

switch (mo2) //MES CERCANO
{
 case "ENERO": mes2="F"; break; 
 case "FEBRERO": mes2="G"; break;
 case "MARZO": mes2="H"; break; 
 case "ABRIL": mes2="J"; break;
 case "MAYO": mes2="K"; break;
 case "JUNIO": mes2="M"; break;
 case "JULIO": mes2="N"; break;
 case "AGOSTO": mes2="Q"; break;
 case "SEPTIEMBRE": mes2="U"; break;
 case "OCTUBRE": mes2="V"; break;
 case "NOVIEMBRE": mes2="X"; break;
 case "DICIEMBRE": mes2="Z"; break;
}

//cambiar mes1 por mes2 si queremos pintarlo al revés
if (mercado == "ORO") { symbol1 = "QGC"+mes1+anyo; symbol2 = "QGC"+mes2+anyo; }
if (mercado == "CRUDO") { symbol1 = "QCL"+mes1+anyo; symbol2 = "QCL"+mes2+anyo; }
if (mercado == "SOJA") { symbol1 = "@S"+mes1+anyo; symbol2 = "@S"+mes2+anyo; }
if (mercado == "MAGRO") { symbol1 = "@HE"+mes1+anyo; symbol2 = "@HE"+mes2+anyo; }
if (mercado == "MAIZ") { symbol1 = "@C"+mes1+anyo; symbol2 = "@C"+mes2+anyo; }  
if (mercado == "BONOS") { symbol1 = "@US"+mes1+anyo; symbol2 = "@US"+mes2+anyo; }
if (mercado == "EURO") { symbol1 = "@EU"+mes1+anyo; symbol2 = "@EU"+mes2+anyo; }
if (mercado == "GAS") { symbol1 = "QNG"+mes1+anyo; symbol2 = "QNG"+mes2+anyo; }
if (mercado == "VIX") { symbol1 = "@VX"+mes1+anyo; symbol2 = "@VX"+mes2+anyo; }


//CARGAMOS EL SEGUNDO SIMBOLO//
SetForeign( Symbol2 );
C2 = C; H2 = H; L2 = L; O2 = O; //EL SIMBOLO 2 CONTIENE LA PATA NO SELECCIONADA DEL SPREAD
RestorePriceArrays();

//LA DIFERENCIA O SPREAD LA LLAMAMOS "A"//
A = C-C2; 

//MOVIMIENTO MEDIO DIARIO O ATR CON VENTANA DE 100 (MUCHOS DÍAS ESTÁ PARADO)
ATR_A = Sum(abs(A-Ref(A,-1)),100)/100; 

//---------------SISTEMA DE TRADING TIPO MERSI--------------

//VARIABLES
med = Param("MEDIA",20,20,200,10);
Banda_inf = 30;
Banda_sup = 70;
per = Param("Periodo Osc",14, 7, 20,1);
SL = Param("Stop Loss (Atrs)",6,4,10,1);

//MERCADO ALCISTA O BAJISTA//
alcista = Ref(MA(A,med) > Ref(MA(A,med),-1),-1);
bajista = Ref(MA(A,med) < Ref(MA(A,med),-1),-1);

//SISTEMA DE ENTRADA Y SALIDA MERSI//
Buy = alcista AND RSIa(A,per) < Banda_inf;
Short = bajista AND RSIa(A,per) > Banda_sup;
Sell = RSIa(A,per) > Banda_sup; //SALIDA CON GANANCIA
Cover = RSIa(A,per) < Banda_inf;

//SALIDA CON STOP//
stop = Nz(ATR_A*SL);
Sell = Sell OR A < ValueWhen(Buy,A-stop);
Cover = Cover OR A > ValueWhen(Short,A+stop);

//QUITAR SEÑALES EXTRA//
Buy = ExRem(Buy,Sell);
Sell = ExRem(Sell,Buy);
Short = ExRem(Short,Cover);
Cover = ExRem(Cover,Short);

//descomentar para mostrar solo como indicador
//Buy = Sell = Short = Cover = 0;

//----------------------------------------------
//LARGO O CORTO//
largo = Flip(Buy, Sell);
corto = Flip(Short,Cover);

//STOP LOSS GRAFICO//
stopline = IIf(largo, ValueWhen(Buy,A-stop), IIf(corto, ValueWhen(Short,A+stop), Null));
Plot(stopline,"SL",colorRed,styleDashed);

//PINTAR LA MEDIA//
Plot(MA(A,med),"MA("+med+")",colorRed,styleLine);

//PINTAR (LO QUE SE PINTA ES A)
PlotOHLC( O-O2, H-H2, L-L2, C-C2, "( - "+Symbol2+ " + " + Name() + " ) spread", Colorblack, styleLine|styleThick,0,0,0,0,2);
PlotShapes(IIf(Buy,shapeUpArrow,shapeNone),colorGreen,0,A,-15); 
PlotShapes(IIf(Buy,shapeHollowCircle,shapeNone),colorGreen,0,A,0); 
PlotShapes(IIf(Sell,shapeDownArrow,shapeNone),colorRed,0,A,-15); 
PlotShapes(IIf(Sell,shapeHollowCircle,shapeNone),colorRed,0,A,0); 
PlotShapes(IIf(short,shapedownarrow,shapeNone),colorBrown,0,A,-15); 
PlotShapes(IIf(short,shapeHollowCircle,shapeNone),colorBrown,0,A,0); 
PlotShapes(IIf(cover,shapeuparrow,shapeNone),colorGrey40,0,A,-15); 
PlotShapes(IIf(cover,shapeHollowCircle,shapeNone),colorGrey40,0,A,0); 

//PLOTTEXT// 
dist = ATR_A;
for( i = 0; i < BarCount; i++ )  
{  
if( Buy[i] ) PlotText( "Long "+NumToStr(ValueWhen(Buy[i],A[i]),1.2), i, A[ i ]-dist[i], colorGreen );  
if( Sell[i] && !Short[i]) PlotText( "Exit " + NumToStr(ValueWhen(Sell[i],A[i]),1.2), i, A[ i ]+dist[i], colorRed );  
if( Short[i] ) PlotText( "Short "+NumToStr(ValueWhen(Short[i],A[i]),1.2), i, A[ i ]+dist[i], colorBrown );  
if( Cover[i] && !Buy[i]) PlotText( "Cover " + NumToStr(ValueWhen(Cover[i],A[i]),1.2), i, A[ i ]-dist[i], colorBlack );  
}  

//CHART// 
SetChartOptions(0,chartShowDates); 
Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Close %g (%.1f%%) {{VALUES}}", A, SelectedValue( ROC( A, 1 ) ) )  
+"\n"+ mo2 + " = " + C + " ; " + mo1 + " = " + C2
+"\n"+ FullName()+"\n"+EncodeColor(colorBlue)+"SISTEMA CALENDAR SPREAD "  
+"\n"+EncodeColor(colorRed) + "SPREAD "+ mercado + " ( - " + mo2 + " +  " + mo1 + " )"
+"\n"+EncodeColor(colorGrey40)+"ATR = "+WriteVal(dist,1.2)+" Pts ; ";

//COMPROBAR SI EL TICKER ES CORRECTO//
if( Name() != symbol1  )
 { GfxSetBkColor( 11); GfxSelectFont( "Tahoma", 20 ); 
GfxSetBkMode( 2 ); GfxTextOut("SELECT: "+symbol1, 40, 20 ); } 

No hay comentarios:

Publicar un comentario

ENTRADAS POPULARES