├── MA_CROS_RSI.mq5 ├── README.md └── MM_CROS_IFR.mq5 /MA_CROS_RSI.mq5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafaelfvcs/Introduction-to-MetaTrader5-and-MQL5---book/HEAD/MA_CROS_RSI.mq5 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction-to-MetaTrader5-and-MQL5---book 2 | Expert Advisor taught in the book: Introduction to MetaTrader 5 and Programming with MQL5. Create your 1st Investment Robot with MQL5 step by step from ZERO. 3 | 2018. 4 | -------------------------------------------------------------------------------- /MM_CROS_IFR.mq5: -------------------------------------------------------------------------------- 1 | //+------------------------------------------------------------------+ 2 | //| MM_CROS_IFR.mq5 | 3 | //| Copyright 2018. | 4 | //| https://www.mql5.com | 5 | //+------------------------------------------------------------------+ 6 | #property copyright "rafaelfvcs. Copyright 2018." 7 | #property link "https://www.mql5.com" 8 | #property version "1.00" 9 | //--- 10 | //-------------------------------------------------------------------+ 11 | // Atenção: EA para fins APENAS didáticos! 12 | // Isso aqui não confere orientação e/ou sugestão de investimentos! 13 | // O autor não se responsabilizar pelo uso indevido deste material 14 | //-------------------------------------------------------------------+ 15 | 16 | // Meus cursos - https://linktr.ee/rafaelfvcs 17 | 18 | enum ESTRATEGIA_ENTRADA 19 | { 20 | APENAS_MM, // Apenas Médias Móveis 21 | APENAS_IFR, // Apenas IFR 22 | MM_E_IFR // Médias mais IFR 23 | }; 24 | 25 | //--- 26 | // Variáveis Input 27 | sinput string s0; //-----------Estratégia de Entrada------------- 28 | input ESTRATEGIA_ENTRADA estrategia = APENAS_MM; // Estratégia de Entrada Trader 29 | 30 | sinput string s1; //-----------Médias Móveis------------- 31 | input int mm_rapida_periodo = 12; // Periodo Média Rápida 32 | input int mm_lenta_periodo = 32; // Periodo Média Lenta 33 | input ENUM_TIMEFRAMES mm_tempo_grafico = PERIOD_CURRENT;// Tempo Gráfico 34 | input ENUM_MA_METHOD mm_metodo = MODE_EMA; // Método 35 | input ENUM_APPLIED_PRICE mm_preco = PRICE_CLOSE; // Preço Aplicado 36 | 37 | sinput string s2; //-----------IFR------------- 38 | input int ifr_periodo = 5; // Período IFR 39 | input ENUM_TIMEFRAMES ifr_tempo_grafico = PERIOD_CURRENT;// Tempo Gráfico 40 | input ENUM_APPLIED_PRICE ifr_preco = PRICE_CLOSE; // Preço Aplicado 41 | 42 | input int ifr_sobrecompra = 70; // Nível de Sobrecompra 43 | input int ifr_sobrevenda = 30; // Nível de Sobrevenda 44 | 45 | sinput string s3; //--------------------------- 46 | input int num_lots = 100; // Número de Lotes 47 | input double TK = 60; // Take Profit 48 | input double SL = 30; // Stop Loss 49 | 50 | sinput string s4; //--------------------------- 51 | input string hora_limite_fecha_op = "17:40"; // Horário Limite Fechar Posição 52 | 53 | //+------------------------------------------------------------------+ 54 | //| Variáveis para os indicadores | 55 | //+------------------------------------------------------------------+ 56 | //--- Médias Móveis 57 | // RÁPIDA - menor período 58 | int mm_rapida_Handle; // Handle controlador da média móvel rápida 59 | double mm_rapida_Buffer[]; // Buffer para armazenamento dos dados das médias 60 | 61 | // LENTA - maior período 62 | int mm_lenta_Handle; // Handle controlador da média móvel lenta 63 | double mm_lenta_Buffer[]; // Buffer para armazenamento dos dados das médias 64 | 65 | //--- IFR 66 | int ifr_Handle; // Handle controlador para o IFR 67 | double ifr_Buffer[]; // Buffer para armazenamento dos dados do IFR 68 | 69 | //+------------------------------------------------------------------+ 70 | //| Variáveis para as funçoes | 71 | //+------------------------------------------------------------------+ 72 | 73 | int magic_number = 123456; // Nº mágico do robô 74 | 75 | MqlRates velas[]; // Variável para armazenar velas 76 | MqlTick tick; // variável para armazenar ticks 77 | 78 | //+------------------------------------------------------------------+ 79 | //| Expert initialization function | 80 | //+------------------------------------------------------------------+ 81 | int OnInit() 82 | { 83 | //--- 84 | mm_rapida_Handle = iMA(_Symbol,mm_tempo_grafico,mm_rapida_periodo,0,mm_metodo,mm_preco); 85 | mm_lenta_Handle = iMA(_Symbol,mm_tempo_grafico,mm_lenta_periodo,0,mm_metodo,mm_preco); 86 | 87 | ifr_Handle = iRSI(_Symbol,ifr_tempo_grafico,ifr_periodo,ifr_preco); 88 | 89 | if(mm_rapida_Handle<0 || mm_lenta_Handle<0 || ifr_Handle<0) 90 | { 91 | Alert("Erro ao tentar criar Handles para o indicador - erro: ",GetLastError(),"!"); 92 | return(-1); 93 | } 94 | 95 | CopyRates(_Symbol,_Period,0,4,velas); 96 | ArraySetAsSeries(velas,true); 97 | 98 | // Para adicionar no gráfico o indicador: 99 | ChartIndicatorAdd(0,0,mm_rapida_Handle); 100 | ChartIndicatorAdd(0,0,mm_lenta_Handle); 101 | ChartIndicatorAdd(0,1,ifr_Handle); 102 | //--- 103 | 104 | //--- 105 | return(INIT_SUCCEEDED); 106 | } 107 | //+------------------------------------------------------------------+ 108 | //| Expert deinitialization function | 109 | //+------------------------------------------------------------------+ 110 | void OnDeinit(const int reason) 111 | { 112 | //--- 113 | IndicatorRelease(mm_rapida_Handle); 114 | IndicatorRelease(mm_lenta_Handle); 115 | IndicatorRelease(ifr_Handle); 116 | } 117 | //+------------------------------------------------------------------+ 118 | //| Expert tick function | 119 | //+------------------------------------------------------------------+ 120 | void OnTick() 121 | { 122 | //--- 123 | // Copiar um vetor de dados tamanho três para o vetor mm_Buffer 124 | CopyBuffer(mm_rapida_Handle,0,0,4,mm_rapida_Buffer); 125 | CopyBuffer(mm_lenta_Handle,0,0,4,mm_lenta_Buffer); 126 | 127 | CopyBuffer(ifr_Handle,0,0,4,ifr_Buffer); 128 | 129 | //--- Alimentar Buffers das Velas com dados: 130 | CopyRates(_Symbol,_Period,0,4,velas); 131 | ArraySetAsSeries(velas,true); 132 | 133 | // Ordenar o vetor de dados: 134 | ArraySetAsSeries(mm_rapida_Buffer,true); 135 | ArraySetAsSeries(mm_lenta_Buffer,true); 136 | ArraySetAsSeries(ifr_Buffer,true); 137 | //--- 138 | 139 | // Alimentar com dados variável de tick 140 | SymbolInfoTick(_Symbol,tick); 141 | 142 | // LOGICA PARA ATIVAR COMPRA 143 | bool compra_mm_cros = mm_rapida_Buffer[0] > mm_lenta_Buffer[0] && 144 | mm_rapida_Buffer[2] < mm_lenta_Buffer[2] ; 145 | 146 | bool compra_ifr = ifr_Buffer[0] <= ifr_sobrevenda; 147 | 148 | // LÓGICA PARA ATIVAR VENDA 149 | bool venda_mm_cros = mm_lenta_Buffer[0] > mm_rapida_Buffer[0] && 150 | mm_lenta_Buffer[2] < mm_rapida_Buffer[2]; 151 | 152 | bool venda_ifr = ifr_Buffer[0] >= ifr_sobrecompra; 153 | //--- 154 | 155 | bool Comprar = false; // Pode comprar? 156 | bool Vender = false; // Pode vender? 157 | 158 | if(estrategia == APENAS_MM) 159 | { 160 | Comprar = compra_mm_cros; 161 | Vender = venda_mm_cros; 162 | 163 | } 164 | else if(estrategia == APENAS_IFR) 165 | { 166 | Comprar = compra_ifr; 167 | Vender = venda_ifr; 168 | } 169 | else 170 | { 171 | Comprar = compra_mm_cros && compra_ifr; 172 | Vender = venda_mm_cros && venda_ifr; 173 | } 174 | 175 | // retorna true se tivermos uma nova vela 176 | bool temosNovaVela = TemosNovaVela(); 177 | 178 | // Toda vez que existir uma nova vela entrar nesse 'if' 179 | if(temosNovaVela) 180 | { 181 | 182 | // Condição de Compra: 183 | if(Comprar && PositionSelect(_Symbol)==false) 184 | { 185 | desenhaLinhaVertical("Compra",velas[1].time,clrBlue); 186 | CompraAMercado(); 187 | } 188 | 189 | // Condição de Venda: 190 | if(Vender && PositionSelect(_Symbol)==false) 191 | { 192 | desenhaLinhaVertical("Venda",velas[1].time,clrRed); 193 | VendaAMercado(); 194 | } 195 | 196 | } 197 | 198 | if(TimeToString(TimeCurrent(),TIME_MINUTES) == hora_limite_fecha_op && PositionSelect(_Symbol)==true) 199 | { 200 | Print("-----> Fim do Tempo Operacional: encerrar posições abertas!"); 201 | 202 | if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) 203 | { 204 | FechaCompra(); 205 | } 206 | else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) 207 | { 208 | FechaVenda(); 209 | } 210 | } 211 | 212 | } 213 | //+------------------------------------------------------------------+ 214 | //+------------------------------------------------------------------+ 215 | //| FUNÇÕES PARA AUXILIAR NA VISUALIZAÇÃO DA ESTRATÉGIA | 216 | //+------------------------------------------------------------------+ 217 | 218 | void desenhaLinhaVertical(string nome, datetime dt, color cor = clrAliceBlue) 219 | { 220 | ObjectDelete(0,nome); 221 | ObjectCreate(0,nome,OBJ_VLINE,0,dt,0); 222 | ObjectSetInteger(0,nome,OBJPROP_COLOR,cor); 223 | } 224 | 225 | //+------------------------------------------------------------------+ 226 | //| FUNÇÕES PARA ENVIO DE ORDENS | 227 | //+------------------------------------------------------------------+ 228 | 229 | // COMPRA A MERCADO 230 | void CompraAMercado() // bser na documentação ordem das variaveis!!! 231 | { 232 | MqlTradeRequest requisicao; // requisição 233 | MqlTradeResult resposta; // resposta 234 | 235 | ZeroMemory(requisicao); 236 | ZeroMemory(resposta); 237 | 238 | //--- Cacacterísticas da ordem de Compra 239 | requisicao.action = TRADE_ACTION_DEAL; // Executa ordem a mercado 240 | requisicao.magic = magic_number; // Nº mágico da ordem 241 | requisicao.symbol = _Symbol; // Simbolo do ativo 242 | requisicao.volume = num_lots; // Nº de Lotes 243 | requisicao.price = NormalizeDouble(tick.ask,_Digits); // Preço para a compra 244 | requisicao.sl = NormalizeDouble(tick.ask - SL*_Point,_Digits);// Preço Stop Loss 245 | requisicao.tp = NormalizeDouble(tick.ask + TK*_Point,_Digits);// Alvo de Ganho - Take Profit 246 | requisicao.deviation = 0; // Desvio Permitido do preço 247 | requisicao.type = ORDER_TYPE_BUY; // Tipo da Ordem 248 | requisicao.type_filling = ORDER_FILLING_FOK; // Tipo deo Preenchimento da ordem 249 | 250 | //--- 251 | OrderSend(requisicao,resposta); 252 | //--- 253 | if(resposta.retcode == 10008 || resposta.retcode == 10009) 254 | { 255 | Print("Ordem de Compra executada com sucesso!"); 256 | } 257 | else 258 | { 259 | Print("Erro ao enviar Ordem Compra. Erro = ", GetLastError()); 260 | ResetLastError(); 261 | } 262 | } 263 | 264 | // VENDA A MERCADO 265 | void VendaAMercado() 266 | { 267 | MqlTradeRequest requisicao; // requisição 268 | MqlTradeResult resposta; // resposta 269 | 270 | ZeroMemory(requisicao); 271 | ZeroMemory(resposta); 272 | 273 | //--- Cacacterísticas da ordem de Venda 274 | requisicao.action = TRADE_ACTION_DEAL; // Executa ordem a mercado 275 | requisicao.magic = magic_number; // Nº mágico da ordem 276 | requisicao.symbol = _Symbol; // Simbolo do ativo 277 | requisicao.volume = num_lots; // Nº de Lotes 278 | requisicao.price = NormalizeDouble(tick.bid,_Digits); // Preço para Venda 279 | requisicao.sl = NormalizeDouble(tick.bid + SL*_Point,_Digits);// Preço Stop Loss 280 | requisicao.tp = NormalizeDouble(tick.bid - TK*_Point,_Digits);// Alvo de Ganho - Take Profit 281 | requisicao.deviation = 0; // Desvio Permitido do preço 282 | requisicao.type = ORDER_TYPE_SELL; // Tipo da Ordem 283 | requisicao.type_filling = ORDER_FILLING_FOK; // Tipo deo Preenchimento da ordem 284 | //--- 285 | OrderSend(requisicao,resposta); 286 | //--- 287 | if(resposta.retcode == 10008 || resposta.retcode == 10009) 288 | { 289 | Print("Ordem de Venda executada com sucesso!"); 290 | } 291 | else 292 | { 293 | Print("Erro ao enviar Ordem Venda. Erro = ", GetLastError()); 294 | ResetLastError(); 295 | } 296 | } 297 | 298 | //--- 299 | void FechaCompra() 300 | { 301 | MqlTradeRequest requisicao; // requisição 302 | MqlTradeResult resposta; // resposta 303 | 304 | ZeroMemory(requisicao); 305 | ZeroMemory(resposta); 306 | 307 | //--- Cacacterísticas da ordem de Venda 308 | requisicao.action = TRADE_ACTION_DEAL; 309 | requisicao.magic = magic_number; 310 | requisicao.symbol = _Symbol; 311 | requisicao.volume = num_lots; 312 | requisicao.price = 0; 313 | requisicao.type = ORDER_TYPE_SELL; 314 | requisicao.type_filling = ORDER_FILLING_RETURN; 315 | 316 | //--- 317 | OrderSend(requisicao,resposta); 318 | //--- 319 | if(resposta.retcode == 10008 || resposta.retcode == 10009) 320 | { 321 | Print("Ordem de Venda executada com sucesso!"); 322 | } 323 | else 324 | { 325 | Print("Erro ao enviar Ordem Venda. Erro = ", GetLastError()); 326 | ResetLastError(); 327 | } 328 | } 329 | 330 | void FechaVenda() 331 | { 332 | MqlTradeRequest requisicao; // requisição 333 | MqlTradeResult resposta; // resposta 334 | 335 | ZeroMemory(requisicao); 336 | ZeroMemory(resposta); 337 | 338 | //--- Cacacterísticas da ordem de Compra 339 | requisicao.action = TRADE_ACTION_DEAL; 340 | requisicao.magic = magic_number; 341 | requisicao.symbol = _Symbol; 342 | requisicao.volume = num_lots; 343 | requisicao.price = 0; 344 | requisicao.type = ORDER_TYPE_BUY; 345 | requisicao.type_filling = ORDER_FILLING_RETURN; 346 | 347 | //--- 348 | OrderSend(requisicao,resposta); 349 | 350 | //--- 351 | if(resposta.retcode == 10008 || resposta.retcode == 10009) 352 | { 353 | Print("Ordem de Compra executada com sucesso!"); 354 | } 355 | else 356 | { 357 | Print("Erro ao enviar Ordem Compra. Erro = ", GetLastError()); 358 | ResetLastError(); 359 | } 360 | } 361 | //+------------------------------------------------------------------+ 362 | //| FUNÇÕES ÚTEIS | 363 | //+------------------------------------------------------------------+ 364 | //--- Para Mudança de Candle 365 | bool TemosNovaVela() 366 | { 367 | //--- memoriza o tempo de abertura da ultima barra (vela) numa variável 368 | static datetime last_time=0; 369 | //--- tempo atual 370 | datetime lastbar_time= (datetime) SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); 371 | 372 | //--- se for a primeira chamada da função: 373 | if(last_time==0) 374 | { 375 | //--- atribuir valor temporal e sair 376 | last_time=lastbar_time; 377 | return(false); 378 | } 379 | 380 | //--- se o tempo estiver diferente: 381 | if(last_time!=lastbar_time) 382 | { 383 | //--- memorizar esse tempo e retornar true 384 | last_time=lastbar_time; 385 | return(true); 386 | } 387 | //--- se passarmos desta linha, então a barra não é nova; retornar false 388 | return(false); 389 | } 390 | --------------------------------------------------------------------------------