- MAGIC NUMBER - TAKE PROFIT Y STOP LOSS - TP Y SL OCULTOS - TRAILING STOP - FILTRO HORARIO Y DIARIO - FILTRO DE SPREAD - MM : 2 % DE RIESGO KELLY MARTINGALA ANTIMARTINGALA RATIO FIJA O FIXED RATIO (SIMPLE, AVANZADO) FRACCIÓN FIJA O FIXED FRACTIONAL (PERIÓDICA, DEL BENEFICIO, ÓPTIMA, F-SEGURA, MEDIDA, PORCENTAJE DE KELLY) PRECIO EFECTIVO TANO - CADA TICK /OPEN PRICE - EXTERNALIZAR - CRUCE ALCISTA/BAJISTA - SUBIDA O BAJADA DE X PIPS - TRADING ALCISTA - PASAR EA DE 4 A 5 DÍGITOS - CAMBIO DE LOTE A MICROLOTE - ÓRDENES LIMITADAS - EAS BASADOS EN INDICADORES - VARIOS MAGIC NUMBER El número mágico es uno de los parámetros (parámetro opcional) de la función OrderSend: int OrderSend( string symbol , int cmd , double volume , double price, int slippage , double stoploss , double takeprofit , string comment=NULL , int magic=0 , datetime expiration =0 , color arrow_color=CLR_NONE) OrderSend() es la función que se utiliza en MQL4 para abrir una nueva orden (orden de inmediato o pendiente) y el parámetro magic (el parámetro noveno) es un valor entero que establece un número mágico de la orden abierta.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
- MAGIC NUMBER
- TAKE PROFIT Y STOP LOSS
- TP Y SL OCULTOS
- TRAILING STOP
- FILTRO HORARIO Y DIARIO
- FILTRO DE SPREAD
- MM :
2 % DE RIESGO
KELLY
MARTINGALA
ANTIMARTINGALA
RATIO FIJA O FIXED RATIO (SIMPLE, AVANZADO)
FRACCIÓN FIJA O FIXED FRACTIONAL (PERIÓDICA, DEL BENEFICIO,
ÓPTIMA, F-SEGURA, MEDIDA, PORCENTAJE DE KELLY)
PRECIO EFECTIVO
TANO
- CADA TICK /OPEN PRICE
- EXTERNALIZAR
- CRUCE ALCISTA/BAJISTA
- SUBIDA O BAJADA DE X PIPS
- TRADING ALCISTA
- PASAR EA DE 4 A 5 DÍGITOS
- CAMBIO DE LOTE A MICROLOTE
- ÓRDENES LIMITADAS
- EAS BASADOS EN INDICADORES
- VARIOS
MAGIC NUMBER
El número mágico es uno de los parámetros (parámetro opcional) de la función OrderSend:
int OrderSend( string symbol , int cmd , double volume , double price, int slippage , double stoploss , double takeprofit , string comment=NULL , int magic=0 , datetime expiration =0 , color arrow_color=CLR_NONE)
OrderSend() es la función que se utiliza en MQL4 para abrir una nueva orden (orden de inmediato o pendiente) y el parámetro magic (el parámetro noveno) es un valor entero que establece un número mágico de la orden abierta.
Ejemplo de uso de Magic Number:
Nuestro ejemplo es un Asesor Experto que abre 4 órdenes de compra (sin condiciones) y cierra todo cuando el beneficio total de ellos alcanza los 100 pips o la pérdida total es de -100 pips.
Con la ayuda de la utilización de nuestro Número Mágico el Expert Advisor es lo suficientemente inteligente como para saber si la orden ha sido abierta por sí mismo o ha sido abierta por otro asesor experto o manualmente.
El asesor experto en el primer lugar ha definido (declarado) la variable integer MagicNumber para usarla más adelante en el código.
int MagicNumber = 101030;
El asesor experto abre 4 órdenes de compra y usa la función ProfitLossMonitor() para controlar la cantidad de la ganancia o pérdida. Pero, ¿cómo puede el asesor experto saber que la orden ha sido abierta por él o por otro asesor experto?
El asesor experto verifica el MagicNumber de la orden seleccionada devuelto por OrderMagicNumber() contra la variable MagicNumber para saber si es nuestra orden o no:
if (OrderMagicNumber() == MagicNumber)
Cuando el total de ganancia es igual a 100 o el total de la pérdida igual a -100 el Asesor Experto llama a la función CloseAll() para cerrar todas las órdenes abiertas que se han abierto por los asesores expertos. Y antes de cerrar las órdenes el Expert Advisor comprueba de nuevo el MagicNumber de la orden seleccionada devuelto por OrderMagicNumber() contra la variable MagicNumber.
¿Sin utilizar Magic Number podría imaginar el funcionamiento de este tipo de asesores expertos? ¿Cómo se calcula la ganancia y la pérdida de sus órdenes? ¿Cómo iban a cerrar solo sus órdenes?
¡Es por eso que el Número Mágico es esencial!
Añadir un Magic Number:
Después del "comentario" en cada función OrderSend:
Reemplaza el valor 0 por Magic.
Busca esta línea: OrderSymbol()==Symbol() en el OrderClose, OrderModify y OrderDelete. Por lo general, están insertadas en instrucciones IF.
Dentro de la línea después de y para cada aparición, se agrega:
&& OrderMagicNumber()==Magic
Finalmente, después de los parámetros extern, se agrega lo siguiente:
extern int Magic=2009; // donde 2009 es un número único para el EA
Poner la declaración MagicNumber inmediatamente después de cualquier declaración #property, #include or #import y antes de las funciones Init, Deinit y Start.
OrderSend(Symbol(),OP_SELL,1,Ask,3,StopLossSell,TakeProfitSell,"My order #2",16384,0,Green);
TP Y SL OCULTOS
- Para evitar que el bróker te barra el SL con repuntes repentinos o spikes se puede poner el SL en 100-300 pips y usar el bloque Close Order If de FEAG. En Amount usa la cantidad de la casilla de beneficios de MT 4 (se pone 10 si se quiere que cierre cuando el beneficio sea mayor a 10 euros o dólares, según sea la divisa en que se abrió la cuenta. Se pone -10 para que cierre cuando la pérdida sea mayor a 10. En CompareAmount se suele poner >)
1) Poner como parámetros externos:
extern bool HideSL=false;//|---------------------hide stop loss
extern bool HideTP=false;//|---------------------hide take profit
2) En algún lugar del EA, después de las condiciones, cerca de los tickets, por ejemplo, añadir lo siguiente:
if(TrailingStop>0)MoveTrailingStop();3) Por último, en la parte superior del EA añadir lo siguiente:
extern int TrailingStop=0;extern int TrailingStep=0;
FILTRO HORARIO Y DIARIOLos dos filtros:1) Declara estas variables ne la parte superior:extern int EndHour = 18;extern int StartHour = 9;bool StopTrading;2) A continuación, crea este método en algún lugar en la parte inferior del EA:void CheckTime(){int h=TimeHour(TimeCurrent());if(((h>EndHour || h<StartHour) && StartHour<EndHour) ||((h<EndHour || h>StartHour) && StartHour>EndHour)){StopTrading=true;}}3) Luego, en la función start pon esto: StopTrading = false; CheckTime(); if(StopTrading==false) { //The trading logic of the EA goes here }Para un filtro de día es el mismo, excepto donde diceint h=TimeHour(TimeCurrent());cambialo porint d=TimeDayOfWeek(DayOfWeek());
Y cambiar toda la "h" a "d" en la función de chqueo del tiempo. Además declarar las variables en la parte superior para StartDay y EndDay (Son un int que van desde 0-6 y 0 es domingo, 1 es lunes, etc.)
Filtro horario1) Poner como parámetros externos:
extern int StartHour=0;extern int EndHour=23;
2) Poner en int start() {//-------------------------------------------------------------------+// time check//-------------------------------------------------------------------if((Hour()>=StartHour)&&(Hour()<=EndHour)){int TradeTimeOk=1;}else{ TradeTimeOk=0; }
3) Poner en la OrderSend de compra y de ventaif(TradeTimeOk==1){- Filter Hours de FEAG://-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.5 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// exported variablesextern int HoursFrom1 = 1;extern int HoursTo1 = 23;
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique namesint current = 0;
datetime BarTime2 = 0;
int init(){
NDigits = Digits; if (false) ObjectsDeleteAll(); // clear the chart Comment(""); // clear the chart}
void OnEveryNewBar2(){ if (true == false && false) PipValue = 10; if (true && (NDigits == 3 || NDigits == 5)) PipValue = 10; if (BarTime2 < Time[0]) { // we have a new bar opened BarTime2 = Time[0]; // keep the new bar open time HoursFilter1(); }}
int deinit(){ if (false) ObjectsDeleteAll(); }- Weekday Filter de FEAG://-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.5 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique namesint current = 0;
datetime BarTime2 = 0;
int init(){ NDigits = Digits; if (false) ObjectsDeleteAll(); // clear the chart Comment(""); // clear the chart}
void OnEveryNewBar2(){ if (true == false && false) PipValue = 10; if (true && (NDigits == 3 || NDigits == 5)) PipValue = 10; if (BarTime2 < Time[0]) { // we have a new bar opened BarTime2 = Time[0]; // keep the new bar open time WeekdayFilter1(); }}
FILTRO DE SPREAD1) Al principio del código, después de los parámetros externos, añadir:extern int MaxSpread=2;2) Después de start() {, añadir:if((Ask-Bid)>MaxSpread*Point)return(0);
MM 2 % DE RIESGO
1) //Money Management sequence if (MoneyManagement)
{ if (Risk<1 || Risk>100) { Comment("Invalid Risk Value."); return(0); } else {Lot=MathFloor((AccountFreeMargin() *AccountLeverage()*Risk*Point*100)/(Ask*MarketInfo(Symbol(),MODE_LOTSIZE)*MarketInfo(Symbol(),MODE_MINLOT )))*MarketInfo(Symbol(),MODE_MINLOT ); } }2) En la parte superior del experto, añadir:extern bool MoneyManagement=True;extern double Risk=2;
KELLYKelly MMb = ratio ganancia/pérdida,p = % de operaciones ganadoras,q = % de operaciones perdedoras (= 1-p),K = porcentaje de saldo a arriesgar por operación.
fórmula de Kelly: K = (b * p - q) / b
La gestión del riesgo de kelly se supone que ayuda a recuperarse de las pérdidas anteriores.1) En los parámetros externos, añadir:extern double initialrisk=0.1;extern int mintradeskelly=10;extern int maxtradeskelly=50;
extern double stoploss=50;2) Después de loa parámetros externos, añadir:int lotsize;3) Añadir en la función init:if(MarketInfo(Symbol(),MODE_MINLOT)>=1){lotsize=100000;}if(MarketInfo(Symbol(),MODE_MINLOT)<1){lotsize=10000;}if(MarketInfo(Symbol(),MODE_MINLOT)<0.1){lotsize=1000;}4) Función de Kellydouble kelly(){ int count=0; double countprofit=0; double countloss=0; int countpve=0; int countnve=0; double b=0; double p=0; double q=0; double k=0;
return(initialrisk);}5) Standard function MM:double mm(double risk,double stoploss){ double lot; if(stoploss>0)lot=AccountBalance()*(risk/100)/(stoploss*pt/MarketInfo(Symbol(),MODE_TICKSIZE)*MarketInfo(Symbol(),MODE_TICKVALUE)); else lot=nd((AccountBalance()/lotsize)*0.01*risk,2); if(lot<MarketInfo(Symbol(),MODE_MINLOT))lot=MarketInfo(Symbol(),MODE_MINLOT); if(lot>MarketInfo(Symbol(),MODE_MAXLOT))lot=MarketInfo(Symbol(),MODE_MAXLOT); return(lot);}6) Reemplazar lots en las funciones Ordersend con:mm(kelly(),stoploss)* Pequeña actualización a la fórmula:if(KellyMinusRisk){k=(((100*(p-q))/count)+100)*0.5*0.01*Klots;}else{k=((((100*(q-p))/count)+100)*0.01*Klots)+Klots;}Klots = lots (soporta usar mm o no)
KellyMinusRisk - si es true- los lotes se deducen cuando ocurre una pérdida, si es false se agregan cuando ocurre una pérdida.
Los lotes "Kelly" se calculan entre 0 y 100% de los lotes que se utilizan.Así que con (KellyMinusRisk=true)Si gana el 100% los lotes Kelly = Lots.con cada pérdida los lotes dejan un porcentaje de los lotes.
Si pierde el 100% los lotes kelly=0.01 lotes.
(KellyMinusRisk=false) ocurre lo contrario. A más pérdidas mayor tamaño de los lotes (Tamaño del lote + hasta el 100% del tamaño del lote)
He estado probando contra el MM regular y encuentro que con KellyMinusRisk = false se está dando mejores resultados.
por ejemplo,MM regular30.6% DDPF1.54Beneficio=69003
//////////////////////////////////////////////////////////////////////////////////////////////////// chceck trades if they do not have set sl and tp than modify tradebool CheckStops(){ double sl=0, tp=0, loss; double total=OrdersTotal(); int ticket=-1; for(int cnt=total-1;cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderType()<=OP_SELL // check for opened position && OrderSymbol()==Symbol() // check for symbol && OrderMagicNumber() == magicNumber) // my magic number { if(OrderType()==OP_BUY) { if(OrderStopLoss()==0 || OrderTakeProfit()==0) { ticket=OrderTicket();
if(tp-Bid<=MarketInfo(Symbol(),MODE_STOPLEVEL)*Point) tp = Bid+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; // last selected is from history so we have to select trade again if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) return(false); if(OrderModify(OrderTicket(),OrderOpenPrice(),sl,tp,0,Green)) // modify position { } else return (false); } } if(OrderType()==OP_SELL) { if(OrderStopLoss()==0 && OrderTakeProfit()==0) { ticket=OrderTicket(); while (!IsTradeAllowed()) Sleep(500); RefreshRates(); SelectLastHistoryOrder(Symbol(), magicNumber);
if(Ask-tp<=MarketInfo(Symbol(),MODE_STOPLEVEL)*Point) tp = Ask-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; // last selected is from history so we have to select trade again if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) return(false); if(OrderModify(OrderTicket(),OrderOpenPrice(),sl,tp,0,Green)) // modify position { } else return (false); } } } } return (true);}
//////////////////////////////////////////////////////////////////////////////////////////////////bool OpenOrderCheck(){ double olots=lots; int ticket; int total=OpenTradesForMNandPairType(magicNumber, Symbol()); if(total==0) { // check for long position (BUY) possibility
while (!IsTradeAllowed()) Sleep(500); RefreshRates(); ticket=OrderSend(Symbol(),OP_BUY,olots,Ask,maxSlippage, 0,0,"",magicNumber,0,Green); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) { stopsChecked = false; Print("BUY order opened : ",OrderOpenPrice()); return (true); } } else { Print("Error opening BUY order : ",GetLastError()); return(false); } } // check for short position (SELL) possibility if(EnterSellCondition()) // OrderSelect() was in function EnterBuyCondition { if(!noHistory) { SelectLastHistoryOrder(Symbol(), magicNumber); if(OrderProfit()<0) { olots=OrderLots()*lotsMultiplier; } } while (!IsTradeAllowed()) Sleep(500); RefreshRates(); ticket=OrderSend(Symbol(),OP_SELL,olots,Bid,maxSlippage, 0,0,"",magicNumber,0,Red); if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{ stopsChecked = false; Print("SELL order opened : ",OrderOpenPrice()); return (true); } } else { Print("Error opening SELL order : ",GetLastError()); return (false); } } } return (true); }
//////////////////////////////////////////////////////////////////////////////////////////////////int OpenTradesForMNandPairType(int iMN, string sOrderSymbol){ int icnt, itotal, retval;
retval=0; itotal=OrdersTotal();
for(icnt=itotal-1;icnt>=0;icnt--) // for loop { OrderSelect(icnt, SELECT_BY_POS, MODE_TRADES); // check for opened position, symbol & MagicNumber if (OrderSymbol()== sOrderSymbol) { if (OrderMagicNumber()==iMN) retval++; } // sOrderSymbol } // for loop
return(retval);}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////double ProfitCheck(){ double profit=0; int total = OrdersTotal(); for (int cnt = total-1 ; cnt >=0 ; cnt--) { OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES); if (OrderSymbol()==Symbol() && (OrderMagicNumber() == magicNumber)) profit+=OrderProfit(); } return(profit); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int Opened(){ int total = OrdersTotal(); int count = 0; for (int cnt = total-1 ; cnt >=0 ; cnt--) { OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES); if (OrderSymbol()==Symbol() && (OrderMagicNumber() == magicNumber)) if(OrderType()==OP_BUY || OrderType()==OP_SELL) count++; } return (count);}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////double Lots(){ int total = OrdersTotal(); double lots = 0; for (int cnt = total-1 ; cnt >=0 ; cnt--) { OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES); if (OrderSymbol()==Symbol() && (OrderMagicNumber() == magicNumber)) if(OrderType()==OP_BUY || OrderType()==OP_SELL) lots+=OrderLots(); } return (lots);}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////bool SelectLastHistoryOrder(string symbol, int magicNumber){ int lastOrder=NULL; for(int i=OrdersHistoryTotal()-1;i>=0;i--)
//////////////////////////////////////////////////////////////////////////////////////////////////int HistoryForMNandPT(int iMN, string sOrderSymbol){ int icnt, itotal, retval;
retval=0; itotal=OrdersHistoryTotal();
for(icnt=itotal-1;icnt>=0;icnt--) // for loop { OrderSelect(icnt, SELECT_BY_POS, MODE_HISTORY); // check for opened position, symbol & MagicNumber if (OrderSymbol()== sOrderSymbol) { if (OrderMagicNumber()==iMN) retval++; } // sOrderSymbol } // for loop
} if((TimeCurrent() >= start && TimeCurrent() < stop) || (TimeCurrent() >= start1 && TimeCurrent() < stop1)) { return(true); } return(false);}- En rojo aparece lo que hay que añadir para poner la martingala y semi-martingala por lotes en FEAG. Ver Buy y Sell Order Lots en FEAG.
- P: Una pregunta usando el bloque de "Buy Order Risk Fixed". El comentario del bloque dice: ------------------
... Otras fórmulas son también posibles en el parámetro de Risk Balance ...
--------------------
Sólo en la lista predeterminada o en propias fórmulas? Si en propias fórmulas es posibles, ¿cómo puedo cambiar el parámetro de risk balance? Quiero reducir AccountFreeMargin() con un valor determinado (por ejemplo, $ 1.000). R: Usted puede cambiar la fórmula en el código generado por MT4. Busque en la línea que contiene la variable "maxlots". double maxlots = AccountFreeMarginO /100 * BalanceRiskPercent2/lotsize * pipsize; Usted puede cambiar a: double maxlots = AccountFreeMarginO - 1234/100 * BalanceRiskPercent2/lotsize * pipsize; Aquí la cantidad es de $ 1,234. Escogí esta cantidad en vez de $ 1,000 por lo que sería fácil de ver en la fórmula. Te adjunto captura de pantalla del código original generado. Si cambias el código manualmente, asegúrete de guardarlo con otro nombre, ya que Generador la próxima vez que se sobrescribirá tus cambios.
P: Hola y gracias por la respuesta, yo esperaba que hubiera una manera de hacerlo en Forex Generador. Así que hice lo siguiente: < double maxlots = (AccountFreeMargin() – AccountFreeMargin() * 0.2 ) /100 * BalanceRiskPercent34/lotsize * pipsize;> Trabaja muy bien ...
ANTIMARTINGALA
Tenga en cuenta que esta martingala no es conventionnal. El tamaño de lotes se
incrementa cuando hay una pérdida, y se reduce cuando es un beneficio. Aunque se
debe empezar de nuevo con el lotage inicial cuando la última serie de pérdidas
4) En la función mm (si tiene una), agregar:&& (martingale==false || (martingale && lastprofit>=0))5) Antes de cada función ordersend, añadir:if(martingale)ilots=mlots;else ilots=lots;6) Finalmente, reemplaza lots en la función ordersend por ilots.
//---- Static variablesstatic int MagicNumber;static int handle;static double LastLot;static double LastBalance;static int Delta; static double MyMinLot;
//+------------------------------------------------------------------+//| expert initialization function |//+------------------------------------------------------------------+int init() {//----
MagicNumber=MagicfromSymbol(); if ( WriteLog ) handle=FileOpen(LogFileName(),FILE_CSV|FILE_WRITE);
InitializeLot();
//---- return(0);
}//+------------------------------------------------------------------+//| expert deinitialization function |//+------------------------------------------------------------------+int deinit() {//---- if ( WriteLog ) FileClose(handle);
//---- return(0); }//+------------------------------------------------------------------+//| expert start function |//+------------------------------------------------------------------+int start() {//----
OpenBuy(Ask);
OpenSell(Bid); //---- return(0); }//+------------------------------------------------------------------+// Auxiliary functions go here//+------------------------------------------------------------------+
int MagicfromSymbol() { int MagicNumber=0; for (int i=0; i<5; i++) { MagicNumber=MagicNumber*3+StringGetChar(Symbol(),i); } MagicNumber=MagicNumber*3+Period(); return(MagicNumber); }
void InitializeLot() {// based on Ryan Jones' Fixed Ratio MM// to be called once on init() section if ( InitialBalance==0 ) { int dathandle=FileOpen(DatFileName(),FILE_CSV|FILE_READ,";"); if (dathandle>0) { InitialBalance=FileReadNumber(dathandle); if ( WriteLog ) WritetoLog("InitialBalance(stored)=$"+DoubleToStr(InitialBalance,2)); FileClose(dathandle); } else { InitialBalance=AccountFreeMargin();
if ( WriteLog ) WritetoLog("InitialBalance=$"+DoubleToStr(InitialBalance,2)); dathandle=FileOpen(DatFileName(),FILE_CSV|FILE_WRITE,";"); FileWrite(dathandle,InitialBalance); FileClose(dathandle); } } else { if ( WriteLog ) WritetoLog("InitialBalance(configured)=$"+DoubleToStr(InitialBalance,2)); dathandle=FileOpen(DatFileName(),FILE_CSV|FILE_WRITE,";"); FileWrite(dathandle,InitialBalance); FileClose(dathandle); } LastBalance=InitialBalance; Delta=MathRound(InitialBalance*RiskLevel); if ( WriteLog ) WritetoLog("Delta=$"+DoubleToStr(Delta,0)); double DeltaPrecision=MathRound(MathLog(Delta)/MathLog(10)); if ( WriteLog ) WritetoLog("DeltaPrecision="+DoubleToStr(DeltaPrecision,0)); double DeltaPower=MathPow(10,DeltaPrecision-1); if ( WriteLog ) WritetoLog("DeltaPower="+DoubleToStr(DeltaPower,0)); Delta=MathRound(Delta/DeltaPower)*DeltaPower; if ( WriteLog ) WritetoLog("Delta(normalized)=$"+DoubleToStr(Delta,0)); double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE)/100; if ( WriteLog ) WritetoLog("LotSize=$"+DoubleToStr(LotSize,0)); MyMinLot=Delta/LotSize; if ( WriteLog ) WritetoLog("MyMinLot="+DoubleToStr(MyMinLot,2)); double LotStep=MarketInfo(Symbol(),MODE_LOTSTEP); LotPrecision=MathRound(-MathLog(LotStep)/MathLog(10)); if ( WriteLog ) WritetoLog("LotStep="+DoubleToStr(LotStep,LotPrecision)); if ( WriteLog ) WritetoLog("Precision="+DoubleToStr(LotPrecision,0)); MyMinLot=NormalizeDouble(MyMinLot,LotPrecision); if ( MyMinLot<MarketInfo(Symbol(),MODE_MINLOT) ) MyMinLot=MarketInfo(Symbol(),MODE_MINLOT); if ( WriteLog ) WritetoLog("MyMinLot(normalized)="+DoubleToStr(MyMinLot,LotPrecision)); LastLot=MyMinLot;}
double GetSizeLot() { // based on Ryan Jones' Fixed Ratio MM// to be called each time an order is to be sent double OptLots=LastLot; if ( WriteLog ) WritetoLog("Balance=$"+DoubleToStr(AccountBalance(),0)); if ( WriteLog ) WritetoLog("OptLots(initial)="+DoubleToStr(OptLots,LotPrecision)); for ( OptLots=OptLots; AccountFreeMargin()>=InitialBalance+(OptLots/MyMinLot)*(OptLots/MyMinLot+1)/2*MyMinLot*Delta; OptLots=OptLots+MyMinLot ) {} if ( WriteLog ) WritetoLog("OptLots(increased)="+DoubleToStr(OptLots,LotPrecision));
for ( OptLots=OptLots; AccountFreeMargin()<InitialBalance+(OptLots/MyMinLot)*(OptLots/MyMinLot-1)/2*MyMinLot*Delta && OptLots>MyMinLot; OptLots=OptLots-MyMinLot ) {} if ( WriteLog ) WritetoLog("OptLots(decreased)="+DoubleToStr(OptLots,LotPrecision)); if ( OptLots<MyMinLot ) OptLots=MyMinLot; if ( OptLots<MarketInfo(Symbol(),MODE_MINLOT) ) OptLots=MarketInfo(Symbol(),MODE_MINLOT); if ( OptLots>100 ) OptLots=100; if ( WriteLog ) WritetoLog("OptLots(normalized)="+DoubleToStr(OptLots,LotPrecision)); return(OptLots); }
string TimeFrame() { string TF; switch(Period()) { case 1: TF="M1"; break; case 5: TF="M5"; break; case 15: TF="M15"; break; case 30: TF="M30"; break; case 60: TF="H1"; break; case 240: TF="H4"; break; case 1440: TF="D1"; break; case 10080: TF="W1"; break; case 43200: TF="MN"; break; } return(TF);}
Poner extern delante de la variable que queramos poner como parámetro externo. Las variables externas van antes de int init.
CRUCE ALCISTA/BAJISTA
- Compra con cruce alcista de SMA 10 a SMA 20 y venta a la inversa. No abre una operación (p.e. compra) si otra de la misma naturaleza (p.e. compra) está abierta y no se ha cerrado (IfOrderDoesNotExist).//-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.4 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// exported variablesextern double BuyLots11 = 0.1;extern int BuyStoploss11 = 20;extern int BuyTakeprofit11 = 30;extern double SellLots15 = 0.1;extern int SellStoploss15 = 20;extern int SellTakeprofit15 = 30;
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique namesint current = 0;
int init(){ NDigits = Digits; if (false) ObjectsDeleteAll(); // clear the chart Comment(""); // clear the chart}
int deinit(){ if (false) ObjectsDeleteAll(); }- Compra con cruce alcista del RSI sobre 30 y venta con cruce bajista del RSI sobre 70. No abre una operación (p.e. compra) si otra de la misma naturaleza (p.e. compra) está abierta y no se ha cerrado (IfOrderDoesNotExist).//-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.4 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// exported variablesextern double BuyLots11 = 0.1;extern int BuyStoploss11 = 20;extern int BuyTakeprofit11 = 30;extern double SellLots15 = 0.1;extern int SellStoploss15 = 20;extern int SellTakeprofit15 = 30;
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique names
int current = 0;
int init(){ NDigits = Digits; if (false) ObjectsDeleteAll(); // clear the chart Comment(""); // clear the chart}
En este caso (last_direction no igual que current_direction) que tenemos que restablecer
nuestra last_direction asignándole el valor de la current_direction.
Y devolveremos el valor de la last_direction. Este valor será 1 si la primera línea está por
encima de la segunda línea y 2 si la primera línea está por debajo de la segunda línea.
else{
return (0);}
Si no (last_direction es igual a current_directio) no hay ningún cambio en la dirección de las
líneas y tenemos que devolver 0.
Nuestro programa llamará a esta función en el cuerpo de su función start() y utiliza el valor
devuelto para determinar la acción apropiada.
SUBIDA O BAJADA DE X PIPSIfGap de FEAG://-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.5 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique namesint current = 0;
datetime BarTime2 = 0;
int init(){ NDigits = Digits; if (false) ObjectsDeleteAll(); // clear the chart Comment(""); // clear the chart}
void OnEveryNewBar2(){ if (true == false && false) PipValue = 10; if (true && (NDigits == 3 || NDigits == 5)) PipValue = 10; if (BarTime2 < Time[0]) { // we have a new bar opened BarTime2 = Time[0]; // keep the new bar open time IfGap1(); }}
TRADING ALCISTATradeUp en FEAG://-------------------------------------------------------------// Etasoft Inc. Forex EA and Script Generator version 4.5 EA//-------------------------------------------------------------// Keywords: MT4, Forex EA builder, create EA, expert advisor developer
// exported variablesextern int NewStopLoss1 = 20;extern int NewTakeProfit1 = 30;extern int TradeUpPoint1 = 20;extern double Lots1 = 0.1;
// local variablesdouble PipValue=1; // this variable is here to support 5-digit brokersbool Terminated = false;string LF = "\n"; // use this in custom or utility blocks where you need line feedsint NDigits = 4; // used mostly for NormalizeDouble in Flex type blocksint ObjCount = 0; // count of all objects created on the chart, allows creation of objects with unique namesint current = 0;
void OnEveryNewBar2(){ if (true == false && false) PipValue = 10; if (true && (NDigits == 3 || NDigits == 5)) PipValue = 10; if (BarTime2 < Time[0]) { // we have a new bar opened BarTime2 = Time[0]; // keep the new bar open time TradeUp1(); }}
void TradeUp1(){ bool exists = false; if (LastTradeUpTicket1 != -1) { for (int j=OrdersTotal()-1; j >= 0; j--) if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES)) { if (OrderTicket() == LastTradeUpTicket1) { exists = true; } } else { Print("OrderSelect() error - ", ErrorDescription(GetLastError())); } } if (exists == false) LastTradeUpTicket1 = -1; // reset Ticket Id so trade-up would be possible double takeprofit = 0; double stoploss = 0;
for (int i=OrdersTotal()-1; i >= 0; i--) if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderSymbol() == Symbol() && OrderMagicNumber() == 1 && LastTradeUpTicket1 == -1) { if (OrderType() == OP_BUY && Ask - OrderOpenPrice() > TradeUpPoint1*PipValue*Point) { takeprofit = Ask+NewTakeProfit1*PipValue*Point; if (NewTakeProfit1 == 0) takeprofit = OrderTakeProfit(); stoploss = Ask-NewStopLoss1*PipValue*Point; if (NewStopLoss1 == 0) stoploss = OrderStopLoss(); LastTradeUpTicket1 = OrderTicket(); int ticket = -1; if (true) ticket = OrderSend(Symbol(), OP_BUY, Lots1, Ask, 4, 0, 0, "My Expert", 1, 0, White); else ticket = OrderSend(Symbol(), OP_BUY, Lots1, Ask, 4, stoploss, takeprofit, "My Expert", 1, 0, White); if (ticket > -1) { if (true) { OrderSelect(ticket, SELECT_BY_TICKET); bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), stoploss, takeprofit, 0, White); if (ret == false) Print("OrderModify() error - ", ErrorDescription(GetLastError())); } } } if (OrderType() == OP_SELL && OrderOpenPrice() - Bid > TradeUpPoint1*PipValue*Point) { takeprofit = Bid-NewTakeProfit1*PipValue*Point; if (NewTakeProfit1 == 0) takeprofit = OrderTakeProfit(); stoploss = Bid+NewStopLoss1*PipValue*Point; if (NewStopLoss1 == 0) stoploss = OrderStopLoss(); LastTradeUpTicket1 = OrderTicket(); int ticket2 = -1; if (true)
PASAR EA DE 4 A 5 DÍGITOSEn primer lugar en la parte superior de su EA, justo debajo de las declaraciones de variables externas, poner esta línea ...double dXPoint = 1;Luego, en la función init agrega lo siguiente ...if(Digits == 3 || Digits == 5) { dXPoint = 10; }Buscar todas las ocurrencias de la variable "Point" en el código (Ctrl-F, introduzca "point" - sin comillas - y luego F3 para avanzar). Normalmente estarán en las variables TakeProfit o StopLoss.Entonces, en lugar de, por ejemplo ...TakeProfit * Point;... cambialo a ...(TakeProfit * dXPoint) * Point;Los paréntesis/llaves son muy importantes, así que no los deje fuera.
Una vez que hayas hecho esto te irá bien para la mayor parte de los EAs, pero algunos utilizarán spreads variables de los brókers dentro del código. Puede aparecer así ...double dSpread = MarketInfo(Symbol(), MODE_SPREAD);... cámbialo a ...double dSpread = MarketInfo(Symbol(), MODE_SPREAD) / dXPoint;La otra cosa a tener en cuenta es la variable slipagge. Ahora usted puede cambiarla manualmente mediante, por ejemplo, el cambio de 3 a 300, o puede hacer que esto ocurra automáticamente. Si usted quiere que sea automático sólo cambie lo que ha añadido a la función init para algo parecido a esto ...if(Digits == 3 || Digits == 5) { dXPoint = 10; Slipagge = Slipagge * dXPoint; }¡Eso es!Su EA ahora debe ser compatible con los bróekers de ambos 4 y 5 decimales.PS: Recuerde hacer siempre una copia de seguridad de su EA antes de comenzar a editar el código.
ÓRDENES LIMITADAS- Insertar ordenes limitadas cada "x" pips. Se crean 5 ordenes limites...
double a;
int start()
{
for(int i=1;i<=5;i++)
{ OrderSend(Symbol(),OP_BUYSTOP,0.01,Ask + a+ 0.0020,3,0, Ask+ a +0.0030);
a = a + 0.0020;
}
}
EA que cada vez que se cierre alguna de las ordenes BUYSTOP me cree otra vez esa misma orden...
Es con la función OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)
EAS BASADOS EN INDICADORES
- Compra cuando el precio sale por encima de la 2a desviación estándar de las BB y se cierra la compra cuando el precio rompe por debajo la línea central de las BB. En FEAG se abre la compra así: iBands ( NULL, NULL, 20, 2, O, PRICE_CLOSE, MODE_UPPER, O) < High(O) El cierre de la compra es así: iMA (NULL, 2, O, MODE_SMA, PRICE_CLOSE,O) > Low(O) - Estoy tratando de tener un EA que compare la última barra cerrada contra muchos barras anteriores, por ejemplo, la última barra (1) tienen un bajo mas bajo que las últimas veinte barras (2-21). ¿Hay una manera de hacer esto con un solo bloque, o tengo que usar veinte diferentes bloques que comparen la última barra a cada una de los anteriores veinte barras? R: Te sugiero uses un solo bloque de Análisis Técnico y coloques lo siguiente en él: First Function - Low[1] Compare- < Second Function - Low[iLowest(NULL,0,MODE_HIGH,21 ,2)];
VARIOS
¿Cómo entrar en x pips por encima del último máximo o por debajo del último bajo? P: Los bloques de órdenes pendientes te permiten especificar un número fijo de pips más arriba (por ejemplo) del último alto para colocar una orden Buy Stop. Quiero precisar que el EA coloque una orden de compra a mercado x pips por encima del último alto o x pips por debajo del último bajo. He intentado usar el bloque técnico (High[1] + 0,0001), pero no puede conseguir que funcione. Cualquier ayuda sería muy apreciada. R: El problema con el uso de High[1] es que tal vez High[1] ya está por debajo del precio de mercado actual Así que hay situaciones posibles: 1. High[1]+0,0001 está por debajo del actual AsklBid. 2. High[1]+0.0001 está por encima del actual Ask I Bid. 3. High[1]+0.0001 está demasiado cerca de AsklBid. Por "demasiado cerca" me refiero a que los brókers no te permitirán tener órdenes pendientes demasiado cerca del actual Bid/Ask. Si está demasiado cerca (ejemplo: sólo 2-4 pips de distancia) obtendrás un error del bróker. Mi consejo en general es la siguiente: durante la configuración inicial evita situaciones que pueden causar errores. En lugar de High[1]+0.0001 usa High[1]+0.0095. En este caso es poco probable que tu High[1]+0.0095 está cerca del actual AsklBid. Una vez que consigues que funcione reduce High[1]+0.0095 más cerca de los valores que deseas. Dependiendo de la estrategia que uses puedes encontrar que brokers ponen más restricciones en la configuración comercial. Y cada bróker es diferente en las restricciones. En scalping es especialmente evidente. Verás todo tipo de errores que vienen de los brókers, ya que estarás negociando en rangos de pips muy estrechos.