//+------------------------------------------------------------------+ //| Fiat147-BovespaWINFUT.mq5 | //| marcosptf | //| https://www.mql5.com | //+------------------------------------------------------------------+ /***************************************** * robo Fiat147 para Clear Bovespa WINFUT * * este eh o primeiro robo nosso criado para ser executado em conta demo da clear * que possue 6 estrategias prontas do codigo de exemplo do MT5 que testamos * e teve um resultado razoavel no backtest e estao parametrizados na planilha; * entao com base nos testes realizados estamos agora criando este robo Fiat147 * justamente com este nome por ser o primeiro, o piloto, para que possamos * codar/executar/testar/observar/melhorar * * * estas sao as estrategias que iremos implementar nesta versao: * DarkCloudPiercingLine-RSI * DarkCloudPiercingLine-CCI * BullishBearish-Engulfing-Stoch * BullishBearish-Engulfing-RSI * BullishBearish-Engulfing-MFI * BullishBearish-Engulfing-CCI * */ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include #include //--- service objects CTrade trade; MqlRates rates[]; CTrade ExtTrade; CSymbolInfo ExtSymbolInfo; #define SIGNAL_BUY 1 // Buy signal #define SIGNAL_NOT 0 // no trading signal #define SIGNAL_SELL -1 // Sell signal #define CLOSE_LONG 2 // signal to close Long #define CLOSE_SHORT -2 // signal to close Short #define TAMANHO_LOTE 2 //--- global variables int ExtAvgBodyPeriod, // average candlestick calculation period ExtSignalOpen =0, // Buy/Sell signal ExtSignalClose =0, // signal to close a position ExtIndicatorHandle=INVALID_HANDLE, ExtTrendMAHandle =INVALID_HANDLE; bool ExtPatternDetected=false, // pattern detected ExtConfirmed =false, // pattern confirmed ExtCloseByTime =true, // requires closing by time ExtCheckPassed =true; // status checking error double maxAtual = 0.00, minAtual = 0.00, maxPrev = 0.00, minPrev = 0.00, openAtual = 0.00, closeAtual = 0.00, amplitudeCandle = 0.00, entrada = 0.00, tamanhoLote = 2, //WinFut pontoFiboProfit = 1.618, takeProfit = 0.00; string dataIntraday = NULL, ExtPatternInfo ="", // current pattern information ExtDirection =""; // position opening direction //--- Input parameters input int InpAverBodyPeriod=12; // period for calculating average candlestick size input int InpMAPeriod =5; // Trend MA period input int InpPeriodRSI =37; // RSI period input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type //--- trade parameters input uint InpDuration=10; // position holding time in bars input uint InpSL =200; // Stop Loss in points input uint InpTP =200; // Take Profit in points input uint InpSlippage=10; // slippage in points //--- money management parameters input double InpLot = TAMANHO_LOTE; // lot //--- Expert ID input long InpMagicNumber=120700; // Magic Number //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //EventSetTimer(60); //ArraySetAsSeries(rates, true); Print("InpSL=", InpSL); Print("InpTP=", InpTP); //--- set parameters for trading operations ExtTrade.SetDeviationInPoints(InpSlippage); // slippage ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level ExtAvgBodyPeriod=InpAverBodyPeriod; //--- indicator initialization ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); if(ExtIndicatorHandle==INVALID_HANDLE) { Print("Error creating CCI indicator"); return(INIT_FAILED); } //--- trend moving average ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); if(ExtIndicatorHandle==INVALID_HANDLE) { Print("Error creating Moving Average indicator"); return(INIT_FAILED); } //--- OK return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //EventKillTimer(); //--- release indicator handle IndicatorRelease(ExtIndicatorHandle); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { /** * nova function que obtem o dia atual, atribui a uma nova * variavel chamada de intraday; * depois esta funcion pergunta se o dia de hoje eh igual ao * variavel intraday, se for diferente ele seta a nova data para * intraday e cancela todas as boletagens do dia anterior * que ainda nao foram executadas; */ //validaBoletasIntraday(); //--- save the next bar start time; all checks at bar opening only static datetime next_bar_open=0; //--- Phase 1 - check the emergence of a new bar and update the status if(TimeCurrent()>=next_bar_open) { //--- get the current state of environment on the new bar // namely, set the values of global variables: // ExtPatternDetected - pattern detection // ExtConfirmed - pattern confirmation // ExtSignalOpen - signal to open // ExtSignalClose - signal to close // ExtPatternInfo - current pattern information if(CheckState()) { //--- set the new bar opening time next_bar_open=TimeCurrent(); next_bar_open-=next_bar_open%PeriodSeconds(_Period); next_bar_open+=PeriodSeconds(_Period); //--- report the emergence of a new bar only once within a bar if(ExtPatternDetected && ExtConfirmed) Print(ExtPatternInfo); } else { //--- error getting the status, retry on the next tick return; } } //--- Phase 2 - if there is a signal and no position in this direction if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) { Print("\r\nSignal to open position ", ExtDirection); PositionOpen(); if(PositionExist(ExtSignalOpen)) ExtSignalOpen=SIGNAL_NOT; } //--- Phase 3 - close if there is a signal to close if(ExtSignalClose && PositionExist(ExtSignalClose)) { Print("\r\nSignal to close position ", ExtDirection); CloseBySignal(ExtSignalClose); if(!PositionExist(ExtSignalClose)) ExtSignalClose=SIGNAL_NOT; } //--- Phase 4 - close upon expiration if(ExtCloseByTime && PositionExpiredByTimeExist()) { CloseByTime(); ExtCloseByTime=PositionExpiredByTimeExist(); } } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { } //+------------------------------------------------------------------+ //| Trade function | //+------------------------------------------------------------------+ void OnTrade() { } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { } //+------------------------------------------------------------------+ //| Tester function | //+------------------------------------------------------------------+ double OnTester() { double ret=0.0; return(ret); } //+------------------------------------------------------------------+ //| TesterInit function | //+------------------------------------------------------------------+ void OnTesterInit() { } //+------------------------------------------------------------------+ //| TesterPass function | //+------------------------------------------------------------------+ void OnTesterPass() { } //+------------------------------------------------------------------+ //| TesterDeinit function | //+------------------------------------------------------------------+ void OnTesterDeinit() { } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { } //+------------------------------------------------------------------+ //| BookEvent function | //+------------------------------------------------------------------+ void OnBookEvent(const string &symbol) { } //####################################################################### //functions para horarios Bovespa # //####################################################################### string getTimestampChart() { return (string) TimeCurrent(); } string getTimeDate(string data) { datetime time = (datetime) data; return TimeToString(time, TIME_DATE); } /************************************************************************ * 1)leilao abertura BMF * * neste horario eh representado pela abertura de futuros da BMF, * * um bom horario para operar abertura eh das: * * 09:00 ~ 09:25 * * porque as 09:30 sempre tem noticias que podem bater em nosso stop; * *************************************************************************/ void winLeilaoAberturaBMF() { } /************************************************************************ * 2)abertura Bovespa * * a abertura do mercado a vista Bovespa eh as 10:00h em ponto porem * * como se trata de acoes, na grande maioria das vezes, algumas delas * * ficam um certo tempo em leilao de abertura entao pelo que agente ja * * observou, o WIN nos primeiros 15m fica as vezes sem direção com * * altissima volatilidade, pode bater no stop desnecessariamente, * * entao melhor horario para operar Bovespa eh depois da abertura * * apos o leilao as: * * 10:15h * *************************************************************************/ void winLeilaoAberturaBovespa() { } /************************************************************************* * 3)horario do almoço * * neste horario eh um periodo nulo, por conta que nas bolsas de valores* * os operadores estao em horario de almoço, e tb eh fechamento da * * bolsa da europa, entao geralmente eh um periodo que a volatilidade eh* * baixa, raro os casos de noticias de ultima hora: * * 12:00 ~ 14:00 * **************************************************************************/ void winAlmocoBovespa() { } /************************************************************************* * 4)periodo da tarde * * eh o periodo em que volta com um volume de negociacao mais forte e * * pode fazer o mercado ficar mais direcional: * * 14:00 ~ 17:00 * **************************************************************************/ void winTardeBovespa() { } /************************************************************************** * 5)leilao fechamento BMF * * neste periodo apos as 17:00h o mercado de balcao Bovespa esta fechado * * é permitido operar o WIN porem precisa estar atento porque o volume * * de negociacao geralmente eh muito baixo, unica vantagem eh q * * geralmente ele obedece a mesma direcao de quando foi fechado o mercado* * Bovespa as 17h: * * 17:00 ~ 18:15 * * * * *obs: * * nesta function precisa ter uma funcionalidade de quando o horario * * passar das 17:55h ele precisa stopar todas as boletas nos status: * * ->em aberto * * ->em execucao * * ->pendentes * ***************************************************************************/ void winLeilaoFechamentoBMF() { } /** * primeiro precisamos pegar a data atual do chart * a variavel dataIntraday inicializa NULL * precisamos verificar se a data se hoje eh igual a variavel dataIntraday * se nao for primeiro agente atribui a data chart para a variavel * depois precisamos verificar se existem boletas em aberto sem estar em execucao * se houver cancela todas * agora se houver boletas em execucao agente precisa pesquisar alguma funcao * pra ver se agente consegue fechar ela a mercado; * * se tratando de bovespa agente percebeu/aprendeu que existem mais horarios de corte * por conta de algumas noticias que podem ocorrer no intraday, entao * vamos colocar os horarios que sao disponiveis para negociacao que * devem estar contempladas no nosso codigo: * * 1)abertura BMF * neste horario eh representado pela abertura de futuros da BMF, * um bom horario para operar abertura eh das: * 09:00 ~ 09:25 * porque as 09:30 sempre tem noticias que podem bater em nosso stop; * * 2)abertura Bovespa * a abertura do mercado a vista Bovespa eh as 10:00h em ponto porem * como se trata de acoes, na grande maioria das vezes, algumas delas ficam * um certo tempo em leilao de abertura entao pelo que agente ja observou, * o WIN nos primeiros 15m fica as vezes sem direção com altissima volatilidade, * pode bater no stop desnecessariamente, entao melhor horario para operar Bovespa eh depois * da abertura apos o leilao as: * 10:15h * * 3)horario do almoço * neste horario eh um periodo nulo, por conta que nas bolsas de valores os operadores * estao em horario de almoço, e tb eh fechamento da bolsa da europa, entao geralmente * eh um periodo que a volatilidade eh baixa, raro os casos de noticias de ultima hora: * 12:00 ~ 14:00 * * 4)periodo da tarde * eh o periodo em que volta com um volume de negociacao mais forte e pode fazer o mercado * ficar mais direcional: * 14:00 ~ 17:00 * * 5)leilao fechamento BMF * neste periodo apos as 17:00h o mercado de balcao Bovespa esta fechado, é permitido * operar o WIN porem precisa estar atento porque o volume de negociacao * geralmente eh muito baixo, unica vantagem eh q geralmente ele obedece a mesma * direcao de quando foi fechado o mercado Bovespa as 17h: * 17:00 ~ 18:15 * */ void validaBoletasIntraday() { Alert("\n get data timestamp string => " + getTimeDate(getTimestampChart())); //se a variavel esta diferente significa ou q esta nula //ou o dia do chart virou mercado fechou if(dataIntraday != getTimeDate(getTimestampChart())) { dataIntraday = getTimeDate(getTimestampChart()); //agora precisamos ver como fecha boletas em aberto //depois ver como fechar a mercado boletas em execucao //trade.SellStop(tamanhoLote, entrada, Symbol(), maxAtual, takeProfit, 0, 0, NULL); //sera q este fecha boleta? //parametro eh o TicketID trade.PositionClose(1234); //modifica a boleta //parametros: //symbol, double sl, double tp //trade.PositionModify(); //testar resultados abaixo trade.CheckResultBalance(); trade.CheckResultComment(); trade.CheckResultEquity(); trade.CheckResultMargin(); trade.CheckResultMarginFree(); trade.CheckResultMarginLevel(); trade.CheckResultProfit(); trade.RequestVolume(); trade.RequestActionDescription(); trade.RequestComment(); trade.RequestDeviation(); trade.RequestExpiration(); trade.RequestMagic(); trade.RequestOrder(); trade.RequestPosition(); trade.RequestPositionBy(); trade.RequestPrice(); trade.RequestSL(); trade.RequestStopLimit(); trade.RequestSymbol(); trade.RequestTP(); trade.RequestTypeDescription(); trade.RequestTypeFillingDescription(); trade.RequestTypeTimeDescription(); trade.RequestVolume(); trade.ResultAsk(); trade.ResultBid(); trade.ResultComment(); trade.ResultDeal(); trade.ResultOrder(); trade.ResultPrice(); trade.ResultRetcode(); trade.ResultRetcodeDescription(); trade.ResultRetcodeExternal(); trade.ResultVolume(); } } //############################################################ //functions exclusivas para a estrategia # //DarkCloud-PiercingLine-RSI # //############################################################ //+------------------------------------------------------------------+ //| Get the current environment and check for a pattern | //+------------------------------------------------------------------+ bool CheckState() { //--- check if there is a pattern if(!CheckPattern()) { Print("Error, failed to check pattern"); return(false); } //--- check for confirmation if(!CheckConfirmation()) { Print("Error, failed to check pattern confirmation"); return(false); } //--- if there is no confirmation, cancel the signal if(!ExtConfirmed) ExtSignalOpen=SIGNAL_NOT; //--- check if there is a signal to close a position if(!CheckCloseSignal()) { Print("Error, failed to check the closing signal"); return(false); } //--- if positions are to be closed after certain holding time in bars if(InpDuration) ExtCloseByTime=true; // set flag to close upon expiration //--- all checks done return(true); } //+------------------------------------------------------------------+ //| Open a position in the direction of the signal | //+------------------------------------------------------------------+ bool PositionOpen() { ExtSymbolInfo.Refresh(); ExtSymbolInfo.RefreshRates(); double price=0; //--- Stop Loss and Take Profit are not set by default double stoploss=0.0; double takeprofit=0.0; int digits=ExtSymbolInfo.Digits(); double point=ExtSymbolInfo.Point(); double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); //--- uptrend if(ExtSignalOpen==SIGNAL_BUY) { price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); //--- if Stop Loss is set if(InpSL>0) { if(spread>=InpSL*point) { PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); stoploss = NormalizeDouble(price-spread, digits); } else stoploss = NormalizeDouble(price-InpSL*point, digits); } //--- if Take Profit is set if(InpTP>0) { if(spread>=InpTP*point) { PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); takeprofit = NormalizeDouble(price+spread, digits); } else takeprofit = NormalizeDouble(price+InpTP*point, digits); } if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) { PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); return(false); } } //--- downtrend if(ExtSignalOpen==SIGNAL_SELL) { price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); //--- if Stop Loss is set if(InpSL>0) { if(spread>=InpSL*point) { PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); stoploss = NormalizeDouble(price+spread, digits); } else stoploss = NormalizeDouble(price+InpSL*point, digits); } //--- if Take Profit is set if(InpTP>0) { if(spread>=InpTP*point) { PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); takeprofit = NormalizeDouble(price-spread, digits); } else takeprofit = NormalizeDouble(price-InpTP*point, digits); } if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) { PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); ExtTrade.PrintResult(); Print(" "); return(false); } } return(true); } //+------------------------------------------------------------------+ //| Close a position based on the specified signal | //+------------------------------------------------------------------+ void CloseBySignal(int type_close) { //--- if there is no signal to close, return successful completion if(type_close==SIGNAL_NOT) return; //--- if there are no positions opened by our EA if(PositionExist(ExtSignalClose)==0) return; //--- closing direction long type; switch(type_close) { case CLOSE_SHORT: type=POSITION_TYPE_SELL; break; case CLOSE_LONG: type=POSITION_TYPE_BUY; break; default: Print("Error! Signal to close not detected"); return; } //--- check all positions and close ours based on the signal int positions=PositionsTotal(); for(int i=positions-1; i>=0; i--) { ulong ticket=PositionGetTicket(i); if(ticket!=0) { //--- get the name of the symbol and the position id (magic) string symbol=PositionGetString(POSITION_SYMBOL); long magic =PositionGetInteger(POSITION_MAGIC); //--- if they correspond to our values if(symbol==Symbol() && magic==InpMagicNumber) { if(PositionGetInteger(POSITION_TYPE)==type) { ExtTrade.PositionClose(ticket, InpSlippage); ExtTrade.PrintResult(); Print(" "); } } } } } //+------------------------------------------------------------------+ //| Close positions upon holding time expiration in bars | //+------------------------------------------------------------------+ void CloseByTime() { //--- if there are no positions opened by our EA if(PositionExist(ExtSignalOpen)==0) return; //--- check all positions and close ours based on the holding time in bars int positions=PositionsTotal(); for(int i=positions-1; i>=0; i--) { ulong ticket=PositionGetTicket(i); if(ticket!=0) { //--- get the name of the symbol and the position id (magic) string symbol=PositionGetString(POSITION_SYMBOL); long magic =PositionGetInteger(POSITION_MAGIC); //--- if they correspond to our values if(symbol==Symbol() && magic==InpMagicNumber) { //--- position opening time datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); //--- check position holding time in bars if(BarsHold(open_time)>=(int)InpDuration) { Print("\r\nTime to close position #", ticket); ExtTrade.PositionClose(ticket, InpSlippage); ExtTrade.PrintResult(); Print(" "); } } } } } //+------------------------------------------------------------------+ //| Returns true if there are open positions | //+------------------------------------------------------------------+ bool PositionExist(int signal_direction) { bool check_type=(signal_direction!=SIGNAL_NOT); //--- what positions to search ENUM_POSITION_TYPE search_type=WRONG_VALUE; if(check_type) switch(signal_direction) { case SIGNAL_BUY: search_type=POSITION_TYPE_BUY; break; case SIGNAL_SELL: search_type=POSITION_TYPE_SELL; break; case CLOSE_LONG: search_type=POSITION_TYPE_BUY; break; case CLOSE_SHORT: search_type=POSITION_TYPE_SELL; break; default: //--- entry direction is not specified; nothing to search return(false); } //--- go through the list of all positions int positions=PositionsTotal(); for(int i=0; i=(int)InpDuration)) return(true); } } } //--- open position not found return(false); } //+------------------------------------------------------------------+ //| Checks position closing time in bars | //+------------------------------------------------------------------+ int BarsHold(datetime open_time) { //--- first run a basic simple check if(TimeCurrent()-open_timeAvgBody(1)) && // long body of the white candlestick (long white) (Close(1)Open(2)) && // close within the previous candlestick body (white) (MidOpenClose(2)>CloseAvg(2)) && // uptrend (Open(1)>High(2))) // open above the previous day's High price (open at new high) { ExtPatternDetected=true; ExtSignalOpen=SIGNAL_SELL; ExtPatternInfo="\r\nDark Cloud Cover detected"; ExtDirection="Sell"; return(true); } //--- check Piercing Line if((Close(1)-Open(1)>AvgBody(1)) && // long body of the white candlestick (long white) (Open(2)-Close(2)>AvgBody(1)) && // long body of the previous black candlestick (long black) (Close(1)>Close(2)) && // close within the body (Close(1)60)) { ExtConfirmed=true; ExtPatternInfo+="\r\n Confirmed: RSI>60"; } //--- successful completion of the check return(true); } //+------------------------------------------------------------------+ //| Check if there is a signal to close | //+------------------------------------------------------------------+ bool CheckCloseSignal() { ExtSignalClose=false; //--- if there is a signal to enter the market, do not check the signal to close if(ExtSignalOpen!=SIGNAL_NOT) return(true); //--- check if there is a signal to close a long position if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) { //--- there is a signal to close a long position ExtSignalClose=CLOSE_LONG; ExtDirection="Long"; } //--- check if there is a signal to close a short position if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) { //--- there is a signal to close a short position ExtSignalClose=CLOSE_SHORT; ExtDirection="Short"; } //--- successful completion of the check return(true); } //+------------------------------------------------------------------+ //| RSI indicator value at the specified bar | //+------------------------------------------------------------------+ double RSI(int index) { double indicator_values[]; if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) { //--- if the copying fails, report the error code PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); return(EMPTY_VALUE); } return(indicator_values[0]); } //+------------------------------------------------------------------+ //| SMA value at the specified bar | //+------------------------------------------------------------------+ double CloseAvg(int index) { double indicator_values[]; if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) { //--- if the copying fails, report the error code PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); return(EMPTY_VALUE); } return(indicator_values[0]); } //############################################################ //fim das functions exclusivas para a estrategia # //DarkCloud-PiercingLine-RSI # //############################################################