Então, é exatamente essa a lógica que eu estava usando, com exceção desse "*-1". Mas tentei dessa forma que você colocou acima e também não funcionou. Quando insiro essa funcionalidade o EA não abre ordens.
Não sei se os valores retornados estão em outro formato, e ao comparar com os valores inputados está dando alguma irregularidade.. Ou se eu estou inserindo a rotina no local errado.. Eu coloquei a rotina no final do EA, abaixo das funções (void) de traillingstop e breakeven.
olá Savio,
o "-1" é importante para transformar o valor inputado de perda máxima em negativo, a não ser que vc já input este valor como negativo, aí o "-1" ficaria errado. Pode postar o código para eu testar?
Então, é exatamente essa a lógica que eu estava usando, com exceção desse "*-1". Mas tentei dessa forma que você colocou acima e também não funcionou. Quando insiro essa funcionalidade o EA não abre ordens.
Não sei se os valores retornados estão em outro formato, e ao comparar com os valores inputados está dando alguma irregularidade.. Ou se eu estou inserindo a rotina no local errado.. Eu coloquei a rotina no final do EA, abaixo das funções (void) de traillingstop e breakeven.
Bem estranho mesmo! Deveria funcionar!
Teste também o exemplo abaixo [ou informa limite de perdas negativo (-) ou na hora da verificação multiplica por -1 como sugerido pelo Armando Jr.]:
#include <Trade\Trade.mqh>
CTrade trade;
#include <Controls\Dialog.mqh>
//+------------------------------------------------------------------+//| DADOS DO INDICADOR |//+------------------------------------------------------------------+ #property indicator_chart_window#property indicator_buffers10#property indicator_plots4#property indicator_label1"Average"#property indicator_type1DRAW_COLOR_LINE#property indicator_color1clrDeepSkyBlue,clrPaleVioletRed#property indicator_style1STYLE_SOLID#property indicator_width12#property indicator_label2"Upperband"#property indicator_type2DRAW_LINE#property indicator_color2clrRed#property indicator_style2STYLE_SOLID#property indicator_width22#property indicator_label3"Lowerband"#property indicator_type3DRAW_LINE#property indicator_color3clrRed#property indicator_style3STYLE_SOLID#property indicator_width32#property indicator_label4"Keltner MA trend"#property indicator_type4DRAW_COLOR_BARS#property indicator_color4clrDeepSkyBlue,clrPaleVioletRed#property indicator_style4STYLE_SOLID//enum enPrices
{
pr_close, // Close
pr_open, // Open
pr_high, // High
pr_low, // Low
pr_median, // Median
pr_typical, // Typical
pr_weighted, // Weighted
pr_haclose, // Heiken ashi close
pr_haopen , // Heiken ashi open
pr_hahigh, // Heiken ashi high
pr_halow, // Heiken ashi low
pr_hamedian, // Heiken ashi median
pr_hatypical, // Heiken ashi typical
pr_haweighted, // Heiken ashi weighted
pr_haaverage // Heiken ashi average
};
//enum enMaModes
{
ma_Simple, // Simple moving average
ma_Expo // Exponential moving average
};
//enum enMaVisble
{
mv_Visible, // Middle line visible
mv_NotVisible // Middle line not visible
};
//enum enCandleMode
{
cm_None, // Do not draw candles nor bars
cm_Bars, // Draw as bars
cm_Candles // Draw as candles
};
//enum enAtrMode
{
atr_Rng, // Calculate using range
atr_Atr // Calculate using ATR
};
double channelBo[];
double channelBh[];
double channelBl[];
double channelBc[];
double channelUp[];
double channelDn[];
double ma[];
double colorBuffer[];
double colorBufferb[];
double countBuffer[];
ENUM_TIMEFRAMES timeFrame;
int mtfHandle;
int atrHandle;
bool calculating;
//+------------------------------------------------------------------+//| INPUTS DO INDICADOR |//+------------------------------------------------------------------+inputENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frameinputint MAPeriod = 20; // Moving average periodinput enMaModes MAMethod = ma_Expo; // Moving average typeinput enMaVisble MAVisible = mv_Visible; // Midlle line visible ?input enPrices Price = pr_typical; // Moving average price inputcolor MaColorUp = clrWhite; // Color for slope upinputcolor MaColorDown = clrWhite; // Color for slope downinputint AtrPeriod = 14; // Range periodinputdouble AtrMultiplier = 0.4; // Range multiplierinput enAtrMode AtrMode = atr_Rng; // Range calculating mode input enCandleMode ViewBars = cm_None; // View bars as :inputbool Interpolate = true; // Interpolate mtf datainputdouble DailyProfit = 100.00; // Daily profit limitinputdouble DailyLoss = -100.00; // Daily loss limitinputulong magicNum = 123456; //Magic Numberinputulong desvPts = 0; //Desvio em PontosinputENUM_ORDER_TYPE_FILLING preenchimento = ORDER_FILLING_RETURN;//Preenchimento da Ordem//+------------------------------------------------------------------+//| INPUTS DO ROBÔ |//+------------------------------------------------------------------+inputdouble Contratos = 1; //Nº de Contratosinputdouble stopLoss = 250; //Stop Lossinputdouble takeProfit = 85; //Take Profitinputdouble gatilhoBE = 40; //Gatilho BreakEveninputdouble gatilhoTS = 50; //Gatilho TrailingStopinputdouble stepTS = 40; //Step TrailingStopdouble PRC; //Preço normalizadodouble STL; //StopLoss normalizadodouble TKP; //TakeProfit normalizadodouble Upperband[];
double Lowerband[];
double Average[];
bool posAberta;
bool ordPendente;
bool beAtivo;
MqlTick ultimoTick;
MqlRates rates[];
//Variaveis Globais Para Plotar Indicador no Gráfico\\inthandle_kc = INVALID_HANDLE;
int sub_window=(int)ChartGetInteger(0,0);
//Variaveis Globais do Controle de Operações no Mesmo Candle\\bool Operamos_Nesta_Vela=false;
string TIME_Abertura_Ultimo_Candle;
string Hora_Ultimo_Negocio;
//
CAppDialog AppWindow;
//intOnInit()
{
ChartSetInteger(0, CHART_SHOW_GRID, false);
//+------------------------------------------------------------------+//| INSERIR NÚMERO DA CONTA MT5 |//+------------------------------------------------------------------+ // if (AccountInfoInteger(ACCOUNT_LOGIN) != 00000000)// {// Alert("Você está tentando utilizar o robô numa conta não permitida! Entre em contato com o criador no Telegram: @FitBot");// return(INIT_FAILED);// }
handle_kc = iCustom(Symbol(), Period(), "KeltnerChannel.ex5", TimeFrame, MAPeriod, MAMethod, MAVisible, Price, MaColorUp, MaColorDown, AtrPeriod, AtrMultiplier, AtrMode, ViewBars, Interpolate);
if(handle_kc==INVALID_HANDLE)
{
Print("Erro ao criar Keltner - erro", GetLastError());
return(INIT_FAILED);
}
if(ChartIndicatorsTotal(0,0) < 1)
{
ChartIndicatorAdd(0,0,handle_kc);
}
ArraySetAsSeries(rates, true);
ArraySetAsSeries(Upperband, true);
ArraySetAsSeries(Lowerband, true);
ArraySetAsSeries(Average, true);
trade.SetTypeFilling(preenchimento);
trade.SetDeviationInPoints(desvPts);
trade.SetExpertMagicNumber(magicNum);
//+------------------------------------------------------------------+//| CRIA PAINEL NO GRÁFICO |//+------------------------------------------------------------------+if(!AppWindow.Create(0,"FitBot_2.0",0,20,20,360,324))
return(INIT_FAILED);
int total=AppWindow.ControlsTotal();
CWndClient*myclient;
for(int i=0;i<total;i++)
{
CWnd*obj=AppWindow.Control(i);
string name=obj.Name();
PrintFormat("%d is %s",i,name);
//--- cor if(StringFind(name,"Client")>0)
{
CWndClient *client=(CWndClient*)obj;
client.ColorBackground(clrRed);
myclient=client;
Print("client.ColorBackground(clrRed);");
ChartRedraw();
}
if(StringFind(name,"Back")>0)
{
CPanel *panel=(CPanel*) obj;
panel.ColorBackground(clrWhite);
Print("panel.ColorBackground(clrWhite);");
ChartRedraw();
}
}
Sleep(500);
myclient.Destroy();
AppWindow.Run();
return(INIT_SUCCEEDED);
}
voidOnDeinit(constint reason)
{
ChartIndicatorDelete(0, sub_window, ChartIndicatorName(0, sub_window, 0));
handle_kc=INVALID_HANDLE;
AppWindow.Destroy(reason);
}
voidOnTick()
{
. . .
double ProfitD1 = CurrentDayProfit();if(ProfitD1 < DailyProfit && ProfitD1 > DailyLoss)
{
if(CheckTradePause(1) && rates[2].close > Lowerband[2] && rates[2].close < Upperband[2] && rates[1].open < Upperband[1] && rates[1].open > Lowerband[1] && rates[1].close > Upperband[1] && !posAberta && !ordPendente && Operamos_Nesta_Vela==false)
{
PRC = NormalizeDouble(ultimoTick.ask, _Digits);
STL = NormalizeDouble(PRC - stopLoss, _Digits);
TKP = NormalizeDouble(PRC + takeProfit, _Digits);
if(trade.Buy(Contratos, _Symbol, PRC, STL, TKP, ""))
Hora_Ultimo_Negocio=TimeToString(TimeCurrent(),TIME_SECONDS);
Operamos_Nesta_Vela=true;
}
elseif(CheckTradePause(1) && rates[2].close > Lowerband[2] && rates[2].close < Upperband[2] && rates[1].open < Upperband[1] && rates[1].open > Lowerband[1] && rates[1].close < Lowerband[1] && !posAberta && !ordPendente && Operamos_Nesta_Vela==false)
{
PRC = NormalizeDouble(ultimoTick.bid, _Digits);
STL = NormalizeDouble(PRC + stopLoss, _Digits);
TKP = NormalizeDouble(PRC - takeProfit, _Digits);
if(trade.Sell(Contratos, _Symbol, PRC, STL, TKP, ""))
Hora_Ultimo_Negocio=TimeToString(TimeCurrent(),TIME_SECONDS);
Operamos_Nesta_Vela=true;
}
}
}
//+------------------------------------------------------------------+//| FUNÇÃO TRAILLINGSTOP |//+------------------------------------------------------------------+void TrailingStop(double preco)
{
for(int i = PositionsTotal()-1; i>=0; i--)
{
string symbol = PositionGetSymbol(i);
ulong magic = PositionGetInteger(POSITION_MAGIC);
if(symbol == _Symbol && magic==magicNum)
{
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
double StopLossCorrente = PositionGetDouble(POSITION_SL);
double TakeProfitCorrente = PositionGetDouble(POSITION_TP);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
if(preco >= (StopLossCorrente + gatilhoTS) )
{
double novoSL = NormalizeDouble (StopLossCorrente + stepTS, _Digits);
if(trade.PositionModify(PositionTicket, novoSL, TakeProfitCorrente))
{
Print("TrailingStop - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
else
{
Print("TrailingStop - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
}
}
elseif(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
if(preco <= (StopLossCorrente - gatilhoTS) )
{
double novoSL = NormalizeDouble (StopLossCorrente - stepTS, _Digits);
if(trade.PositionModify(PositionTicket, novoSL, TakeProfitCorrente))
{
Print("TrailingStop - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
else
{
Print("TrailingStop - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
}
}
}
}
}
//+------------------------------------------------------------------+//| FUNÇÃO BREAKEVEN |//+------------------------------------------------------------------+void BreakEven(double preco)
{
for(int i = PositionsTotal()-1; i>=0; i--)
{
string symbol = PositionGetSymbol(i);
ulong magic = PositionGetInteger(POSITION_MAGIC);
if(symbol == _Symbol && magic == magicNum)
{
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
double PrecoEntrada = PositionGetDouble(POSITION_PRICE_OPEN);
double TakeProfitCorrente = PositionGetDouble(POSITION_TP);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
if( preco >= (PrecoEntrada + gatilhoBE) )
{
if(trade.PositionModify(PositionTicket, PrecoEntrada, TakeProfitCorrente))
{
Print("BreakEven - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
beAtivo = true;
}
else
{
Print("BreakEven - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
}
}
elseif(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
if( preco <= (PrecoEntrada - gatilhoBE) )
{
if(trade.PositionModify(PositionTicket, PrecoEntrada, TakeProfitCorrente))
{
Print("BreakEven - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
beAtivo = true;
}
else
{
Print("BreakEven - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
}
}
}
}
}
}
//+------------------------------------------------------------------+//| Verifica se o intervalo para o próximo trade foi cumprido |//+------------------------------------------------------------------+bool CheckTradePause(int nBars)
{
//--- Determina quantas barras até o próximo tradedatetime time_start = iTime(_Symbol, PERIOD_CURRENT, nBars);
if(HistorySelect(time_start, TimeCurrent()))
{
for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
{
constulong Ticket = HistoryDealGetTicket(i);
if(HistoryDealGetString(Ticket, DEAL_SYMBOL) == _Symbol && HistoryDealGetInteger(Ticket, DEAL_MAGIC) == magicNum)
{return(false);}
}
}
else
{
Print("Erro ao recuperar o histórico de operações ...");
return(false);
}
//--- Intervalo cumpridoreturn(true);
}
//+------------------------------------------------------------------+ //| Calcula o lucro / prejuízo do dia atual |//+------------------------------------------------------------------+ double CurrentDayProfit()
{
datetime time_start = (datetime) (86400*(((ulong)TimeCurrent())/86400));
double result = 0.0;
ulong ticket;
int cnt;
if(HistorySelect(time_start, TimeCurrent()))
{
for(cnt = HistoryDealsTotal() - 1; cnt >= 0; cnt--)
{
ticket = HistoryDealGetTicket(cnt);
if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == magicNum)
{
result += HistoryDealGetDouble(ticket, DEAL_PROFIT);
}
}
}
else
{
Print("Erro ao recuperar o histórico de operações...");
}
return(result);
}
//+------------------------------------------------------------------+//| FUNÇÃO DO PAINEL EXIBIDO NO GRÁFICO (AINDA EM CONSTRUÇÃO) |//+------------------------------------------------------------------+voidOnChartEvent(constint id, // ID do evento constlong& lparam, // parâmetro do evento do tipo longconstdouble& dparam, // parâmetro do evento do tipo doubleconststring& sparam) // parâmetro do evento do tipo string
{
AppWindow.ChartEvent(id,lparam,dparam,sparam);
}
//+------------------------------------------------------------------+
Teste também o exemplo abaixo [ou informa limite de perdas negativo (-) ou na hora da verificação multiplica por -1 como sugerido pelo Armando Jr.]:
Deu certo, tanto desse ultimo modo, quanto da forma com que o Armando tinha passado. O problema era na hora de fazer o teste. Fazendo direto pelo meta editor ele só faz corretamente na primeira tentativa, se eu altero algum parâmetro e faço novamente, ele não funciona corretamente. Mas fazendo direto no testador de estratégias está perfeito. mas ele só leva em conta as operações fechadas. Depois vou tentar fazer com ele encerre as operações abertas ao atingir os limites diários.
Mas muito obrigado, Vinicius e Armando!!! Me ajudaram muito!
Vinicius de Oliveira: Em relação ao Martingale, caso você queira mesmo implementar esse sistema, [AQUI] tem vários exemplos de códigos que utilizam esse recurso.
Passei a tarde toda tentando encaixar o martingale, mas to apanhando ainda!! Vou acabar tendo que usar um exemplo que achei no youtube como base (https://www.youtube.com/watch?v=VBC5ArUszTU&t=913s) O triste é que para implementar da forma com que ele ensina eu vou ter, praticamente, que refazer do zero o EA. Tentei fazer de uma forma que não precisasse alterar tanta coisa, mas não rolou ainda.
Ja pensou em usar o modo de debug e entender o que acontece com o seu algoritmo ?
Sim, irmão, com certeza! Sempre rodo no modo visual pra ver oq está saindo errado. Ele está funcionando certinho, tenho que arrumar pra ele ficar mais estético, os inputs e tal.. mas está funcionando certinho!
Em relação ao MG, da forma que eu fiz, ele sempre aumentava o lote, independente de ter tomado o loss na operação anterior ou não. Preciso pegar melhor essa parte. Mas não achei nenhum material em pra tomar como base, não digo nem uma "código base" não, digo um artigo mesmo.
Só preciso inserir essa questão do MG e acertar ele pra fechar as posições a mercado quando atingir os limites diários.
Mas estou feliz com o desenvolvimento do EA, é o meu primeiro contato com esse mundo de programação.. estou apanhando mas está saindo! rs
Eu não disse modo visual e sim modo de debug, assim vc consegue acompanhar passo a passo do seu algoritmo. Embora também seja um teste visual, vc tem acesso a trilha do algoritmo o que leva a um entendimento melhor do que se passa.
Então, é exatamente essa a lógica que eu estava usando, com exceção desse "*-1". Mas tentei dessa forma que você colocou acima e também não funcionou.
Quando insiro essa funcionalidade o EA não abre ordens.
Não sei se os valores retornados estão em outro formato, e ao comparar com os valores inputados está dando alguma irregularidade..
Ou se eu estou inserindo a rotina no local errado.. Eu coloquei a rotina no final do EA, abaixo das funções (void) de traillingstop e breakeven.
olá Savio,
o "-1" é importante para transformar o valor inputado de perda máxima em negativo, a não ser que vc já input este valor como negativo, aí o "-1" ficaria errado. Pode postar o código para eu testar?
Então, é exatamente essa a lógica que eu estava usando, com exceção desse "*-1". Mas tentei dessa forma que você colocou acima e também não funcionou.
Quando insiro essa funcionalidade o EA não abre ordens.
Não sei se os valores retornados estão em outro formato, e ao comparar com os valores inputados está dando alguma irregularidade..
Ou se eu estou inserindo a rotina no local errado.. Eu coloquei a rotina no final do EA, abaixo das funções (void) de traillingstop e breakeven.
Bem estranho mesmo! Deveria funcionar!
Teste também o exemplo abaixo [ou informa limite de perdas negativo (-) ou na hora da verificação multiplica por -1 como sugerido pelo Armando Jr.]:
Bem estranho mesmo! Deveria funcionar!
Teste também o exemplo abaixo [ou informa limite de perdas negativo (-) ou na hora da verificação multiplica por -1 como sugerido pelo Armando Jr.]:
Deu certo, tanto desse ultimo modo, quanto da forma com que o Armando tinha passado.
O problema era na hora de fazer o teste. Fazendo direto pelo meta editor ele só faz corretamente na primeira tentativa, se eu altero algum parâmetro e faço novamente, ele não funciona corretamente.
Mas fazendo direto no testador de estratégias está perfeito.
mas ele só leva em conta as operações fechadas. Depois vou tentar fazer com ele encerre as operações abertas ao atingir os limites diários.
Mas muito obrigado, Vinicius e Armando!!! Me ajudaram muito!
Em relação ao Martingale, caso você queira mesmo implementar esse sistema, [AQUI] tem vários exemplos de códigos que utilizam esse recurso.
Passei a tarde toda tentando encaixar o martingale, mas to apanhando ainda!!
Vou acabar tendo que usar um exemplo que achei no youtube como base (https://www.youtube.com/watch?v=VBC5ArUszTU&t=913s)
O triste é que para implementar da forma com que ele ensina eu vou ter, praticamente, que refazer do zero o EA.
Tentei fazer de uma forma que não precisasse alterar tanta coisa, mas não rolou ainda.
....
Ja pensou em usar o modo de debug e entender o que acontece com o seu algoritmo ?
Ja pensou em usar o modo de debug e entender o que acontece com o seu algoritmo ?
Sim, irmão, com certeza! Sempre rodo no modo visual pra ver oq está saindo errado. Ele está funcionando certinho, tenho que arrumar pra ele ficar mais estético, os inputs e tal.. mas está funcionando certinho!
Em relação ao MG, da forma que eu fiz, ele sempre aumentava o lote, independente de ter tomado o loss na operação anterior ou não.
Preciso pegar melhor essa parte. Mas não achei nenhum material em pra tomar como base, não digo nem uma "código base" não, digo um artigo mesmo.
Só preciso inserir essa questão do MG e acertar ele pra fechar as posições a mercado quando atingir os limites diários.
Mas estou feliz com o desenvolvimento do EA, é o meu primeiro contato com esse mundo de programação.. estou apanhando mas está saindo! rs
....
Eu não disse modo visual e sim modo de debug, assim vc consegue acompanhar passo a passo do seu algoritmo. Embora também seja um teste visual, vc tem acesso a trilha do algoritmo o que leva a um entendimento melhor do que se passa.
OnTradeTransaction - Manipulação de eventos - Referência MQL5 - Referência sobre algorítimo/automatização de negociação na linguagem para MetaTrader 5