Init mql5 project
This commit is contained in:
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"C_Cpp.default.includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/Include"
|
||||
],
|
||||
"C_Cpp.default.compilerPath": "",
|
||||
"C_Cpp.default.intelliSenseMode": "gcc-x64",
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"C_Cpp.autocompleteAddParentheses": true,
|
||||
"files.exclude": {
|
||||
"**/*.ex4": true,
|
||||
"**/*.ex5": true,
|
||||
"**/*_@!!@.mq4": true,
|
||||
"**/*_@!!@.mq5": true,
|
||||
"**/*_@!!@.mqh": true,
|
||||
"**/*_@!!@.log": true
|
||||
},
|
||||
"files.associations": {
|
||||
"*.mqh": "cpp",
|
||||
"*.mq4": "cpp",
|
||||
"*.mq5": "cpp"
|
||||
},
|
||||
"editor.tabSize": 3,
|
||||
"C_Cpp.default.forcedInclude": [
|
||||
"c:\\Users\\thinh\\.vscode\\extensions\\l-i-v.mql-tools-2.2.0\\data\\mql5_en.mqh"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,168 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ExpertMACD.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Include |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Expert\Expert.mqh>
|
||||
#include <Expert\Signal\SignalMACD.mqh>
|
||||
#include <Expert\Trailing\TrailingNone.mqh>
|
||||
#include <Expert\Money\MoneyNone.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- inputs for expert
|
||||
input string Inp_Expert_Title ="ExpertMACD";
|
||||
int Expert_MagicNumber =10981;
|
||||
bool Expert_EveryTick =false;
|
||||
//--- inputs for signal
|
||||
input int Inp_Signal_MACD_PeriodFast =12;
|
||||
input int Inp_Signal_MACD_PeriodSlow =24;
|
||||
input int Inp_Signal_MACD_PeriodSignal=9;
|
||||
input int Inp_Signal_MACD_TakeProfit =50;
|
||||
input int Inp_Signal_MACD_StopLoss =20;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global expert object |
|
||||
//+------------------------------------------------------------------+
|
||||
CExpert ExtExpert;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- Initializing expert
|
||||
if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing expert");
|
||||
ExtExpert.Deinit();
|
||||
return(-1);
|
||||
}
|
||||
//--- Creation of signal object
|
||||
CSignalMACD *signal=new CSignalMACD;
|
||||
if(signal==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-2);
|
||||
}
|
||||
//--- Add signal to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitSignal(signal))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-3);
|
||||
}
|
||||
//--- Set signal parameters
|
||||
signal.PeriodFast(Inp_Signal_MACD_PeriodFast);
|
||||
signal.PeriodSlow(Inp_Signal_MACD_PeriodSlow);
|
||||
signal.PeriodSignal(Inp_Signal_MACD_PeriodSignal);
|
||||
signal.TakeLevel(Inp_Signal_MACD_TakeProfit);
|
||||
signal.StopLevel(Inp_Signal_MACD_StopLoss);
|
||||
//--- Check signal parameters
|
||||
if(!signal.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error signal parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-4);
|
||||
}
|
||||
//--- Creation of trailing object
|
||||
CTrailingNone *trailing=new CTrailingNone;
|
||||
if(trailing==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-5);
|
||||
}
|
||||
//--- Add trailing to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitTrailing(trailing))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-6);
|
||||
}
|
||||
//--- Set trailing parameters
|
||||
//--- Check trailing parameters
|
||||
if(!trailing.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error trailing parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-7);
|
||||
}
|
||||
//--- Creation of money object
|
||||
CMoneyNone *money=new CMoneyNone;
|
||||
if(money==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating money");
|
||||
ExtExpert.Deinit();
|
||||
return(-8);
|
||||
}
|
||||
//--- Add money to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitMoney(money))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing money");
|
||||
ExtExpert.Deinit();
|
||||
return(-9);
|
||||
}
|
||||
//--- Set money parameters
|
||||
//--- Check money parameters
|
||||
if(!money.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error money parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-10);
|
||||
}
|
||||
//--- Tuning of all necessary indicators
|
||||
if(!ExtExpert.InitIndicators())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing indicators");
|
||||
ExtExpert.Deinit();
|
||||
return(-11);
|
||||
}
|
||||
//--- succeed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deinitialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
ExtExpert.Deinit();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "tick" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
ExtExpert.OnTick();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "trade" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade(void)
|
||||
{
|
||||
ExtExpert.OnTrade();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "timer" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer(void)
|
||||
{
|
||||
ExtExpert.OnTimer();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,175 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ExpertMAMA.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Include |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Expert\Expert.mqh>
|
||||
#include <Expert\Signal\SignalMA.mqh>
|
||||
#include <Expert\Trailing\TrailingMA.mqh>
|
||||
#include <Expert\Money\MoneyNone.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- inputs for expert
|
||||
input string Inp_Expert_Title ="ExpertMAMA";
|
||||
int Expert_MagicNumber =12003;
|
||||
bool Expert_EveryTick =false;
|
||||
//--- inputs for signal
|
||||
input int Inp_Signal_MA_Period =12;
|
||||
input int Inp_Signal_MA_Shift =6;
|
||||
input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA;
|
||||
input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE;
|
||||
//--- inputs for trailing
|
||||
input int Inp_Trailing_MA_Period =12;
|
||||
input int Inp_Trailing_MA_Shift =0;
|
||||
input ENUM_MA_METHOD Inp_Trailing_MA_Method =MODE_SMA;
|
||||
input ENUM_APPLIED_PRICE Inp_Trailing_MA_Applied=PRICE_CLOSE;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global expert object |
|
||||
//+------------------------------------------------------------------+
|
||||
CExpert ExtExpert;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- Initializing expert
|
||||
if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing expert");
|
||||
ExtExpert.Deinit();
|
||||
return(-1);
|
||||
}
|
||||
//--- Creation of signal object
|
||||
CSignalMA *signal=new CSignalMA;
|
||||
if(signal==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-2);
|
||||
}
|
||||
//--- Add signal to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitSignal(signal))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-3);
|
||||
}
|
||||
//--- Set signal parameters
|
||||
signal.PeriodMA(Inp_Signal_MA_Period);
|
||||
signal.Shift(Inp_Signal_MA_Shift);
|
||||
signal.Method(Inp_Signal_MA_Method);
|
||||
signal.Applied(Inp_Signal_MA_Applied);
|
||||
//--- Check signal parameters
|
||||
if(!signal.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error signal parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-4);
|
||||
}
|
||||
//--- Creation of trailing object
|
||||
CTrailingMA *trailing=new CTrailingMA;
|
||||
if(trailing==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-5);
|
||||
}
|
||||
//--- Add trailing to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitTrailing(trailing))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-6);
|
||||
}
|
||||
//--- Set trailing parameters
|
||||
trailing.Period(Inp_Trailing_MA_Period);
|
||||
trailing.Shift(Inp_Trailing_MA_Shift);
|
||||
trailing.Method(Inp_Trailing_MA_Method);
|
||||
trailing.Applied(Inp_Trailing_MA_Applied);
|
||||
//--- Check trailing parameters
|
||||
if(!trailing.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error trailing parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-7);
|
||||
}
|
||||
//--- Creation of money object
|
||||
CMoneyNone *money=new CMoneyNone;
|
||||
if(money==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating money");
|
||||
ExtExpert.Deinit();
|
||||
return(-8);
|
||||
}
|
||||
//--- Add money to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitMoney(money))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing money");
|
||||
ExtExpert.Deinit();
|
||||
return(-9);
|
||||
}
|
||||
//--- Set money parameters
|
||||
//--- Check money parameters
|
||||
if(!money.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error money parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-10);
|
||||
}
|
||||
//--- Tuning of all necessary indicators
|
||||
if(!ExtExpert.InitIndicators())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing indicators");
|
||||
ExtExpert.Deinit();
|
||||
return(-11);
|
||||
}
|
||||
//--- succeed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deinitialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
ExtExpert.Deinit();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "tick" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
ExtExpert.OnTick();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "trade" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade(void)
|
||||
{
|
||||
ExtExpert.OnTrade();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "timer" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer(void)
|
||||
{
|
||||
ExtExpert.OnTimer();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,171 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ExpertMAPSAR.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Include |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Expert\Expert.mqh>
|
||||
#include <Expert\Signal\SignalMA.mqh>
|
||||
#include <Expert\Trailing\TrailingParabolicSAR.mqh>
|
||||
#include <Expert\Money\MoneyNone.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- inputs for expert
|
||||
input string Inp_Expert_Title ="ExpertMAPSAR";
|
||||
int Expert_MagicNumber =14598;
|
||||
bool Expert_EveryTick =false;
|
||||
//--- inputs for signal
|
||||
input int Inp_Signal_MA_Period =12;
|
||||
input int Inp_Signal_MA_Shift =6;
|
||||
input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA;
|
||||
input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE;
|
||||
//--- inputs for trailing
|
||||
input double Inp_Trailing_ParabolicSAR_Step =0.02;
|
||||
input double Inp_Trailing_ParabolicSAR_Maximum=0.2;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global expert object |
|
||||
//+------------------------------------------------------------------+
|
||||
CExpert ExtExpert;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- Initializing expert
|
||||
if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing expert");
|
||||
ExtExpert.Deinit();
|
||||
return(-1);
|
||||
}
|
||||
//--- Creation of signal object
|
||||
CSignalMA *signal=new CSignalMA;
|
||||
if(signal==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-2);
|
||||
}
|
||||
//--- Add signal to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitSignal(signal))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-3);
|
||||
}
|
||||
//--- Set signal parameters
|
||||
signal.PeriodMA(Inp_Signal_MA_Period);
|
||||
signal.Shift(Inp_Signal_MA_Shift);
|
||||
signal.Method(Inp_Signal_MA_Method);
|
||||
signal.Applied(Inp_Signal_MA_Applied);
|
||||
//--- Check signal parameters
|
||||
if(!signal.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error signal parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-4);
|
||||
}
|
||||
//--- Creation of trailing object
|
||||
CTrailingPSAR *trailing=new CTrailingPSAR;
|
||||
if(trailing==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-5);
|
||||
}
|
||||
//--- Add trailing to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitTrailing(trailing))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-6);
|
||||
}
|
||||
//--- Set trailing parameters
|
||||
trailing.Step(Inp_Trailing_ParabolicSAR_Step);
|
||||
trailing.Maximum(Inp_Trailing_ParabolicSAR_Maximum);
|
||||
//--- Check trailing parameters
|
||||
if(!trailing.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error trailing parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-7);
|
||||
}
|
||||
//--- Creation of money object
|
||||
CMoneyNone *money=new CMoneyNone;
|
||||
if(money==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating money");
|
||||
ExtExpert.Deinit();
|
||||
return(-8);
|
||||
}
|
||||
//--- Add money to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitMoney(money))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing money");
|
||||
ExtExpert.Deinit();
|
||||
return(-9);
|
||||
}
|
||||
//--- Set money parameters
|
||||
//--- Check money parameters
|
||||
if(!money.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error money parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-10);
|
||||
}
|
||||
//--- Tuning of all necessary indicators
|
||||
if(!ExtExpert.InitIndicators())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing indicators");
|
||||
ExtExpert.Deinit();
|
||||
return(-11);
|
||||
}
|
||||
//--- succeed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deinitialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
ExtExpert.Deinit();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "tick" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
ExtExpert.OnTick();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "trade" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade(void)
|
||||
{
|
||||
ExtExpert.OnTrade();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "timer" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer(void)
|
||||
{
|
||||
ExtExpert.OnTimer();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,176 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ExpertMAPSARSizeOptimized.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Include |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Expert\Expert.mqh>
|
||||
#include <Expert\Signal\SignalMA.mqh>
|
||||
#include <Expert\Trailing\TrailingParabolicSAR.mqh>
|
||||
#include <Expert\Money\MoneySizeOptimized.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- inputs for expert
|
||||
input string Inp_Expert_Title ="ExpertMAPSARSizeOptimized";
|
||||
int Expert_MagicNumber =27893;
|
||||
bool Expert_EveryTick =false;
|
||||
//--- inputs for signal
|
||||
input int Inp_Signal_MA_Period =12;
|
||||
input int Inp_Signal_MA_Shift =6;
|
||||
input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA;
|
||||
input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE;
|
||||
//--- inputs for trailing
|
||||
input double Inp_Trailing_ParabolicSAR_Step =0.02;
|
||||
input double Inp_Trailing_ParabolicSAR_Maximum =0.2;
|
||||
//--- inputs for money
|
||||
input double Inp_Money_SizeOptimized_DecreaseFactor=3.0;
|
||||
input double Inp_Money_SizeOptimized_Percent =10.0;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global expert object |
|
||||
//+------------------------------------------------------------------+
|
||||
CExpert ExtExpert;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- Initializing expert
|
||||
if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing expert");
|
||||
ExtExpert.Deinit();
|
||||
return(-1);
|
||||
}
|
||||
//--- Creation of signal object
|
||||
CSignalMA *signal=new CSignalMA;
|
||||
if(signal==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-2);
|
||||
}
|
||||
//--- Add signal to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitSignal(signal))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing signal");
|
||||
ExtExpert.Deinit();
|
||||
return(-3);
|
||||
}
|
||||
//--- Set signal parameters
|
||||
signal.PeriodMA(Inp_Signal_MA_Period);
|
||||
signal.Shift(Inp_Signal_MA_Shift);
|
||||
signal.Method(Inp_Signal_MA_Method);
|
||||
signal.Applied(Inp_Signal_MA_Applied);
|
||||
//--- Check signal parameters
|
||||
if(!signal.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error signal parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-4);
|
||||
}
|
||||
//--- Creation of trailing object
|
||||
CTrailingPSAR *trailing=new CTrailingPSAR;
|
||||
if(trailing==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-5);
|
||||
}
|
||||
//--- Add trailing to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitTrailing(trailing))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing trailing");
|
||||
ExtExpert.Deinit();
|
||||
return(-6);
|
||||
}
|
||||
//--- Set trailing parameters
|
||||
trailing.Step(Inp_Trailing_ParabolicSAR_Step);
|
||||
trailing.Maximum(Inp_Trailing_ParabolicSAR_Maximum);
|
||||
//--- Check trailing parameters
|
||||
if(!trailing.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error trailing parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-7);
|
||||
}
|
||||
//--- Creation of money object
|
||||
CMoneySizeOptimized *money=new CMoneySizeOptimized;
|
||||
if(money==NULL)
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error creating money");
|
||||
ExtExpert.Deinit();
|
||||
return(-8);
|
||||
}
|
||||
//--- Add money to expert (will be deleted automatically))
|
||||
if(!ExtExpert.InitMoney(money))
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing money");
|
||||
ExtExpert.Deinit();
|
||||
return(-9);
|
||||
}
|
||||
//--- Set money parameters
|
||||
money.DecreaseFactor(Inp_Money_SizeOptimized_DecreaseFactor);
|
||||
money.Percent(Inp_Money_SizeOptimized_Percent);
|
||||
//--- Check money parameters
|
||||
if(!money.ValidationSettings())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error money parameters");
|
||||
ExtExpert.Deinit();
|
||||
return(-10);
|
||||
}
|
||||
//--- Tuning of all necessary indicators
|
||||
if(!ExtExpert.InitIndicators())
|
||||
{
|
||||
//--- failed
|
||||
printf(__FUNCTION__+": error initializing indicators");
|
||||
ExtExpert.Deinit();
|
||||
return(-11);
|
||||
}
|
||||
//--- succeed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deinitialization function of the expert |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
ExtExpert.Deinit();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "tick" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
ExtExpert.OnTick();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "trade" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade(void)
|
||||
{
|
||||
ExtExpert.OnTrade();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function-event handler "timer" |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer(void)
|
||||
{
|
||||
ExtExpert.OnTimer();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Controls.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "ControlsDialog.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables |
|
||||
//+------------------------------------------------------------------+
|
||||
CControlsDialog ExtDialog;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- create application dialog
|
||||
if(!ExtDialog.Create(0,"Controls",0,20,20,360,324))
|
||||
return(INIT_FAILED);
|
||||
//--- run application
|
||||
ExtDialog.Run();
|
||||
//--- succeed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy dialog
|
||||
ExtDialog.Destroy(reason);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert chart event function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id, // event ID
|
||||
const long& lparam, // event parameter of the long type
|
||||
const double& dparam, // event parameter of the double type
|
||||
const string& sparam) // event parameter of the string type
|
||||
{
|
||||
ExtDialog.ChartEvent(id,lparam,dparam,sparam);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,427 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ControlsDialog.mqh |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Controls\Dialog.mqh>
|
||||
#include <Controls\Button.mqh>
|
||||
#include <Controls\Edit.mqh>
|
||||
#include <Controls\DatePicker.mqh>
|
||||
#include <Controls\ListView.mqh>
|
||||
#include <Controls\ComboBox.mqh>
|
||||
#include <Controls\SpinEdit.mqh>
|
||||
#include <Controls\RadioGroup.mqh>
|
||||
#include <Controls\CheckGroup.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- indents and gaps
|
||||
#define INDENT_LEFT (11) // indent from left (with allowance for border width)
|
||||
#define INDENT_TOP (11) // indent from top (with allowance for border width)
|
||||
#define INDENT_RIGHT (11) // indent from right (with allowance for border width)
|
||||
#define INDENT_BOTTOM (11) // indent from bottom (with allowance for border width)
|
||||
#define CONTROLS_GAP_X (5) // gap by X coordinate
|
||||
#define CONTROLS_GAP_Y (5) // gap by Y coordinate
|
||||
//--- for buttons
|
||||
#define BUTTON_WIDTH (100) // size by X coordinate
|
||||
#define BUTTON_HEIGHT (20) // size by Y coordinate
|
||||
//--- for the indication area
|
||||
#define EDIT_HEIGHT (20) // size by Y coordinate
|
||||
//--- for group controls
|
||||
#define GROUP_WIDTH (150) // size by X coordinate
|
||||
#define LIST_HEIGHT (179) // size by Y coordinate
|
||||
#define RADIO_HEIGHT (56) // size by Y coordinate
|
||||
#define CHECK_HEIGHT (93) // size by Y coordinate
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CControlsDialog |
|
||||
//| Usage: main dialog of the Controls application |
|
||||
//+------------------------------------------------------------------+
|
||||
class CControlsDialog : public CAppDialog
|
||||
{
|
||||
private:
|
||||
CEdit m_edit; // the display field object
|
||||
CButton m_button1; // the button object
|
||||
CButton m_button2; // the button object
|
||||
CButton m_button3; // the fixed button object
|
||||
CSpinEdit m_spin_edit; // the up-down object
|
||||
CDatePicker m_date; // the datepicker object
|
||||
CListView m_list_view; // the list object
|
||||
CComboBox m_combo_box; // the dropdown list object
|
||||
CRadioGroup m_radio_group; // the radio buttons group object
|
||||
CCheckGroup m_check_group; // the check box group object
|
||||
|
||||
public:
|
||||
CControlsDialog(void);
|
||||
~CControlsDialog(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
bool CreateEdit(void);
|
||||
bool CreateButton1(void);
|
||||
bool CreateButton2(void);
|
||||
bool CreateButton3(void);
|
||||
bool CreateSpinEdit(void);
|
||||
bool CreateDate(void);
|
||||
bool CreateListView(void);
|
||||
bool CreateComboBox(void);
|
||||
bool CreateRadioGroup(void);
|
||||
bool CreateCheckGroup(void);
|
||||
//--- handlers of the dependent controls events
|
||||
void OnClickButton1(void);
|
||||
void OnClickButton2(void);
|
||||
void OnClickButton3(void);
|
||||
void OnChangeSpinEdit(void);
|
||||
void OnChangeDate(void);
|
||||
void OnChangeListView(void);
|
||||
void OnChangeComboBox(void);
|
||||
void OnChangeRadioGroup(void);
|
||||
void OnChangeCheckGroup(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event Handling |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CControlsDialog)
|
||||
ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
|
||||
ON_EVENT(ON_CLICK,m_button2,OnClickButton2)
|
||||
ON_EVENT(ON_CLICK,m_button3,OnClickButton3)
|
||||
ON_EVENT(ON_CHANGE,m_spin_edit,OnChangeSpinEdit)
|
||||
ON_EVENT(ON_CHANGE,m_date,OnChangeDate)
|
||||
ON_EVENT(ON_CHANGE,m_list_view,OnChangeListView)
|
||||
ON_EVENT(ON_CHANGE,m_combo_box,OnChangeComboBox)
|
||||
ON_EVENT(ON_CHANGE,m_radio_group,OnChangeRadioGroup)
|
||||
ON_EVENT(ON_CHANGE,m_check_group,OnChangeCheckGroup)
|
||||
EVENT_MAP_END(CAppDialog)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CControlsDialog::CControlsDialog(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CControlsDialog::~CControlsDialog(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateEdit())
|
||||
return(false);
|
||||
if(!CreateButton1())
|
||||
return(false);
|
||||
if(!CreateButton2())
|
||||
return(false);
|
||||
if(!CreateButton3())
|
||||
return(false);
|
||||
if(!CreateSpinEdit())
|
||||
return(false);
|
||||
if(!CreateListView())
|
||||
return(false);
|
||||
if(!CreateDate())
|
||||
return(false);
|
||||
if(!CreateRadioGroup())
|
||||
return(false);
|
||||
if(!CreateCheckGroup())
|
||||
return(false);
|
||||
if(!CreateComboBox())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the display field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateEdit(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP;
|
||||
int x2=ClientAreaWidth()-INDENT_RIGHT;
|
||||
int y2=y1+EDIT_HEIGHT;
|
||||
//--- create
|
||||
if(!m_edit.Create(m_chart_id,m_name+"Edit",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_edit.ReadOnly(true))
|
||||
return(false);
|
||||
if(!Add(m_edit))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Button1" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateButton1(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+BUTTON_WIDTH;
|
||||
int y2=y1+BUTTON_HEIGHT;
|
||||
//--- create
|
||||
if(!m_button1.Create(m_chart_id,m_name+"Button1",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button1.Text("Button1"))
|
||||
return(false);
|
||||
if(!Add(m_button1))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Button2" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateButton2(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT+(BUTTON_WIDTH+CONTROLS_GAP_X);
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+BUTTON_WIDTH;
|
||||
int y2=y1+BUTTON_HEIGHT;
|
||||
//--- create
|
||||
if(!m_button2.Create(m_chart_id,m_name+"Button2",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button2.Text("Button2"))
|
||||
return(false);
|
||||
if(!Add(m_button2))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Button3" fixed button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateButton3(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT+2*(BUTTON_WIDTH+CONTROLS_GAP_X);
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+BUTTON_WIDTH;
|
||||
int y2=y1+BUTTON_HEIGHT;
|
||||
//--- create
|
||||
if(!m_button3.Create(m_chart_id,m_name+"Button3",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button3.Text("Locked"))
|
||||
return(false);
|
||||
if(!Add(m_button3))
|
||||
return(false);
|
||||
m_button3.Locking(true);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "SpinEdit" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateSpinEdit(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+(BUTTON_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+EDIT_HEIGHT;
|
||||
//--- create
|
||||
if(!m_spin_edit.Create(m_chart_id,m_name+"SpinEdit",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_spin_edit))
|
||||
return(false);
|
||||
m_spin_edit.MinValue(10);
|
||||
m_spin_edit.MaxValue(1000);
|
||||
m_spin_edit.Value(100);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "DatePicker" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateDate(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT+GROUP_WIDTH+2*CONTROLS_GAP_X;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+(BUTTON_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+EDIT_HEIGHT;
|
||||
//--- create
|
||||
if(!m_date.Create(m_chart_id,m_name+"Date",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_date))
|
||||
return(false);
|
||||
m_date.Value(TimeCurrent());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "ListView" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateListView(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT+GROUP_WIDTH+2*CONTROLS_GAP_X;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(BUTTON_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+2*CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+LIST_HEIGHT-CONTROLS_GAP_Y;
|
||||
//--- create
|
||||
if(!m_list_view.Create(m_chart_id,m_name+"ListView",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_list_view))
|
||||
return(false);
|
||||
//--- fill out with strings
|
||||
for(int i=0;i<16;i++)
|
||||
if(!m_list_view.AddItem("Item "+IntegerToString(i)))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "ComboBox" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateComboBox(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(BUTTON_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+EDIT_HEIGHT;
|
||||
//--- create
|
||||
if(!m_combo_box.Create(m_chart_id,m_name+"ComboBox",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_combo_box))
|
||||
return(false);
|
||||
//--- fill out with strings
|
||||
for(int i=0;i<16;i++)
|
||||
if(!m_combo_box.ItemAdd("Item "+IntegerToString(i)))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "RadioGroup" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateRadioGroup(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(BUTTON_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+RADIO_HEIGHT;
|
||||
//--- create
|
||||
if(!m_radio_group.Create(m_chart_id,m_name+"RadioGroup",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_radio_group))
|
||||
return(false);
|
||||
//--- fill out with strings
|
||||
for(int i=0;i<3;i++)
|
||||
if(!m_radio_group.AddItem("Item "+IntegerToString(i),1<<i))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "CheckGroup" element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CControlsDialog::CreateCheckGroup(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=INDENT_LEFT;
|
||||
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(BUTTON_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(EDIT_HEIGHT+CONTROLS_GAP_Y)+
|
||||
(RADIO_HEIGHT+CONTROLS_GAP_Y);
|
||||
int x2=x1+GROUP_WIDTH;
|
||||
int y2=y1+CHECK_HEIGHT;
|
||||
//--- create
|
||||
if(!m_check_group.Create(m_chart_id,m_name+"CheckGroup",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_check_group))
|
||||
return(false);
|
||||
//--- fill out with strings
|
||||
for(int i=0;i<5;i++)
|
||||
if(!m_check_group.AddItem("Item "+IntegerToString(i),1<<i))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnClickButton1(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnClickButton2(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnClickButton3(void)
|
||||
{
|
||||
if(m_button3.Pressed())
|
||||
m_edit.Text(__FUNCTION__+"On");
|
||||
else
|
||||
m_edit.Text(__FUNCTION__+"Off");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeSpinEdit()
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" : Value="+IntegerToString(m_spin_edit.Value()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeDate(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" \""+TimeToString(m_date.Value(),TIME_DATE)+"\"");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeListView(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" \""+m_list_view.Select()+"\"");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeComboBox(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" \""+m_combo_box.Select()+"\"");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeRadioGroup(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" : Value="+IntegerToString(m_radio_group.Value()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CControlsDialog::OnChangeCheckGroup(void)
|
||||
{
|
||||
m_edit.Text(__FUNCTION__+" : Value="+IntegerToString(m_check_group.Value()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,451 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MACD Sample.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "5.50"
|
||||
#property description "It is important to make sure that the expert works with a normal"
|
||||
#property description "chart and the user did not make any mistakes setting input"
|
||||
#property description "variables (Lots, TakeProfit, TrailingStop) in our case,"
|
||||
#property description "we check TakeProfit on a chart of more than 2*trend_period bars"
|
||||
|
||||
#define MACD_MAGIC 1234502
|
||||
//---
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
#include <Trade\PositionInfo.mqh>
|
||||
#include <Trade\AccountInfo.mqh>
|
||||
//---
|
||||
input double InpLots =0.1; // Lots
|
||||
input int InpTakeProfit =50; // Take Profit (in pips)
|
||||
input int InpTrailingStop =30; // Trailing Stop Level (in pips)
|
||||
input int InpMACDOpenLevel =3; // MACD open level (in pips)
|
||||
input int InpMACDCloseLevel=2; // MACD close level (in pips)
|
||||
input int InpMATrendPeriod =26; // MA trend period
|
||||
//---
|
||||
int ExtTimeOut=10; // time out in seconds between trade operations
|
||||
//+------------------------------------------------------------------+
|
||||
//| MACD Sample expert class |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSampleExpert
|
||||
{
|
||||
protected:
|
||||
double m_adjusted_point; // point value adjusted for 3 or 5 points
|
||||
CTrade m_trade; // trading object
|
||||
CSymbolInfo m_symbol; // symbol info object
|
||||
CPositionInfo m_position; // trade position object
|
||||
CAccountInfo m_account; // account info wrapper
|
||||
//--- indicators
|
||||
int m_handle_macd; // MACD indicator handle
|
||||
int m_handle_ema; // moving average indicator handle
|
||||
//--- indicator buffers
|
||||
double m_buff_MACD_main[]; // MACD indicator main buffer
|
||||
double m_buff_MACD_signal[]; // MACD indicator signal buffer
|
||||
double m_buff_EMA[]; // EMA indicator buffer
|
||||
//--- indicator data for processing
|
||||
double m_macd_current;
|
||||
double m_macd_previous;
|
||||
double m_signal_current;
|
||||
double m_signal_previous;
|
||||
double m_ema_current;
|
||||
double m_ema_previous;
|
||||
//---
|
||||
double m_macd_open_level;
|
||||
double m_macd_close_level;
|
||||
double m_traling_stop;
|
||||
double m_take_profit;
|
||||
|
||||
public:
|
||||
CSampleExpert(void);
|
||||
~CSampleExpert(void);
|
||||
bool Init(void);
|
||||
void Deinit(void);
|
||||
bool Processing(void);
|
||||
|
||||
protected:
|
||||
bool InitCheckParameters(const int digits_adjust);
|
||||
bool InitIndicators(void);
|
||||
bool LongClosed(void);
|
||||
bool ShortClosed(void);
|
||||
bool LongModified(void);
|
||||
bool ShortModified(void);
|
||||
bool LongOpened(void);
|
||||
bool ShortOpened(void);
|
||||
};
|
||||
//--- global expert
|
||||
CSampleExpert ExtExpert;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSampleExpert::CSampleExpert(void) : m_adjusted_point(0),
|
||||
m_handle_macd(INVALID_HANDLE),
|
||||
m_handle_ema(INVALID_HANDLE),
|
||||
m_macd_current(0),
|
||||
m_macd_previous(0),
|
||||
m_signal_current(0),
|
||||
m_signal_previous(0),
|
||||
m_ema_current(0),
|
||||
m_ema_previous(0),
|
||||
m_macd_open_level(0),
|
||||
m_macd_close_level(0),
|
||||
m_traling_stop(0),
|
||||
m_take_profit(0)
|
||||
{
|
||||
ArraySetAsSeries(m_buff_MACD_main,true);
|
||||
ArraySetAsSeries(m_buff_MACD_signal,true);
|
||||
ArraySetAsSeries(m_buff_EMA,true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSampleExpert::~CSampleExpert(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization and checking for input parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::Init(void)
|
||||
{
|
||||
//--- initialize common information
|
||||
m_symbol.Name(Symbol()); // symbol
|
||||
m_trade.SetExpertMagicNumber(MACD_MAGIC); // magic
|
||||
m_trade.SetMarginMode();
|
||||
m_trade.SetTypeFillingBySymbol(Symbol());
|
||||
//--- tuning for 3 or 5 digits
|
||||
int digits_adjust=1;
|
||||
if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
|
||||
digits_adjust=10;
|
||||
m_adjusted_point=m_symbol.Point()*digits_adjust;
|
||||
//--- set default deviation for trading in adjusted points
|
||||
m_macd_open_level =InpMACDOpenLevel*m_adjusted_point;
|
||||
m_macd_close_level=InpMACDCloseLevel*m_adjusted_point;
|
||||
m_traling_stop =InpTrailingStop*m_adjusted_point;
|
||||
m_take_profit =InpTakeProfit*m_adjusted_point;
|
||||
//--- set default deviation for trading in adjusted points
|
||||
m_trade.SetDeviationInPoints(3*digits_adjust);
|
||||
//---
|
||||
if(!InitCheckParameters(digits_adjust))
|
||||
return(false);
|
||||
if(!InitIndicators())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checking for input parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::InitCheckParameters(const int digits_adjust)
|
||||
{
|
||||
//--- initial data checks
|
||||
if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel())
|
||||
{
|
||||
printf("Take Profit must be greater than %d",m_symbol.StopsLevel());
|
||||
return(false);
|
||||
}
|
||||
if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel())
|
||||
{
|
||||
printf("Trailing Stop must be greater than %d",m_symbol.StopsLevel());
|
||||
return(false);
|
||||
}
|
||||
//--- check for right lots amount
|
||||
if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax())
|
||||
{
|
||||
printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
|
||||
return(false);
|
||||
}
|
||||
if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10)
|
||||
{
|
||||
printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep());
|
||||
return(false);
|
||||
}
|
||||
//--- warning
|
||||
if(InpTakeProfit<=InpTrailingStop)
|
||||
printf("Warning: Trailing Stop must be less than Take Profit");
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialization of the indicators |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::InitIndicators(void)
|
||||
{
|
||||
//--- create MACD indicator
|
||||
if(m_handle_macd==INVALID_HANDLE)
|
||||
if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE)
|
||||
{
|
||||
printf("Error creating MACD indicator");
|
||||
return(false);
|
||||
}
|
||||
//--- create EMA indicator and add it to collection
|
||||
if(m_handle_ema==INVALID_HANDLE)
|
||||
if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE)
|
||||
{
|
||||
printf("Error creating EMA indicator");
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for long position closing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::LongClosed(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- should it be closed?
|
||||
if(m_macd_current>0)
|
||||
if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
|
||||
if(m_macd_current>m_macd_close_level)
|
||||
{
|
||||
//--- close position
|
||||
if(m_trade.PositionClose(Symbol()))
|
||||
printf("Long position by %s to be closed",Symbol());
|
||||
else
|
||||
printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
//--- processed and cannot be modified
|
||||
res=true;
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for short position closing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::ShortClosed(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- should it be closed?
|
||||
if(m_macd_current<0)
|
||||
if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
|
||||
if(MathAbs(m_macd_current)>m_macd_close_level)
|
||||
{
|
||||
//--- close position
|
||||
if(m_trade.PositionClose(Symbol()))
|
||||
printf("Short position by %s to be closed",Symbol());
|
||||
else
|
||||
printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
//--- processed and cannot be modified
|
||||
res=true;
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for long position modifying |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::LongModified(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- check for trailing stop
|
||||
if(InpTrailingStop>0)
|
||||
{
|
||||
if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop)
|
||||
{
|
||||
double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits());
|
||||
double tp=m_position.TakeProfit();
|
||||
if(m_position.StopLoss()<sl || m_position.StopLoss()==0.0)
|
||||
{
|
||||
//--- modify position
|
||||
if(m_trade.PositionModify(Symbol(),sl,tp))
|
||||
printf("Long position by %s to be modified",Symbol());
|
||||
else
|
||||
{
|
||||
printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
printf("Modify parameters : SL=%f,TP=%f",sl,tp);
|
||||
}
|
||||
//--- modified and must exit from expert
|
||||
res=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for short position modifying |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::ShortModified(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- check for trailing stop
|
||||
if(InpTrailingStop>0)
|
||||
{
|
||||
if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop))
|
||||
{
|
||||
double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits());
|
||||
double tp=m_position.TakeProfit();
|
||||
if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0)
|
||||
{
|
||||
//--- modify position
|
||||
if(m_trade.PositionModify(Symbol(),sl,tp))
|
||||
printf("Short position by %s to be modified",Symbol());
|
||||
else
|
||||
{
|
||||
printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
printf("Modify parameters : SL=%f,TP=%f",sl,tp);
|
||||
}
|
||||
//--- modified and must exit from expert
|
||||
res=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for long position opening |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::LongOpened(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- check for long position (BUY) possibility
|
||||
if(m_macd_current<0)
|
||||
if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
|
||||
if(MathAbs(m_macd_current)>(m_macd_open_level) && m_ema_current>m_ema_previous)
|
||||
{
|
||||
double price=m_symbol.Ask();
|
||||
double tp =m_symbol.Bid()+m_take_profit;
|
||||
//--- check for free money
|
||||
if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0)
|
||||
printf("We have no money. Free Margin = %f",m_account.FreeMargin());
|
||||
else
|
||||
{
|
||||
//--- open position
|
||||
if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp))
|
||||
printf("Position by %s to be opened",Symbol());
|
||||
else
|
||||
{
|
||||
printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
printf("Open parameters : price=%f,TP=%f",price,tp);
|
||||
}
|
||||
}
|
||||
//--- in any case we must exit from expert
|
||||
res=true;
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for short position opening |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::ShortOpened(void)
|
||||
{
|
||||
bool res=false;
|
||||
//--- check for short position (SELL) possibility
|
||||
if(m_macd_current>0)
|
||||
if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
|
||||
if(m_macd_current>(m_macd_open_level) && m_ema_current<m_ema_previous)
|
||||
{
|
||||
double price=m_symbol.Bid();
|
||||
double tp =m_symbol.Ask()-m_take_profit;
|
||||
//--- check for free money
|
||||
if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_SELL,InpLots,price)<0.0)
|
||||
printf("We have no money. Free Margin = %f",m_account.FreeMargin());
|
||||
else
|
||||
{
|
||||
//--- open position
|
||||
if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,InpLots,price,0.0,tp))
|
||||
printf("Position by %s to be opened",Symbol());
|
||||
else
|
||||
{
|
||||
printf("Error opening SELL position by %s : '%s'",Symbol(),m_trade.ResultComment());
|
||||
printf("Open parameters : price=%f,TP=%f",price,tp);
|
||||
}
|
||||
}
|
||||
//--- in any case we must exit from expert
|
||||
res=true;
|
||||
}
|
||||
//--- result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| main function returns true if any position processed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSampleExpert::Processing(void)
|
||||
{
|
||||
//--- refresh rates
|
||||
if(!m_symbol.RefreshRates())
|
||||
return(false);
|
||||
//--- refresh indicators
|
||||
if(BarsCalculated(m_handle_macd)<2 || BarsCalculated(m_handle_ema)<2)
|
||||
return(false);
|
||||
if(CopyBuffer(m_handle_macd,0,0,2,m_buff_MACD_main) !=2 ||
|
||||
CopyBuffer(m_handle_macd,1,0,2,m_buff_MACD_signal)!=2 ||
|
||||
CopyBuffer(m_handle_ema,0,0,2,m_buff_EMA) !=2)
|
||||
return(false);
|
||||
// m_indicators.Refresh();
|
||||
//--- to simplify the coding and speed up access
|
||||
//--- data are put into internal variables
|
||||
m_macd_current =m_buff_MACD_main[0];
|
||||
m_macd_previous =m_buff_MACD_main[1];
|
||||
m_signal_current =m_buff_MACD_signal[0];
|
||||
m_signal_previous=m_buff_MACD_signal[1];
|
||||
m_ema_current =m_buff_EMA[0];
|
||||
m_ema_previous =m_buff_EMA[1];
|
||||
//--- it is important to enter the market correctly,
|
||||
//--- but it is more important to exit it correctly...
|
||||
//--- first check if position exists - try to select it
|
||||
if(m_position.Select(Symbol()))
|
||||
{
|
||||
if(m_position.PositionType()==POSITION_TYPE_BUY)
|
||||
{
|
||||
//--- try to close or modify long position
|
||||
if(LongClosed())
|
||||
return(true);
|
||||
if(LongModified())
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- try to close or modify short position
|
||||
if(ShortClosed())
|
||||
return(true);
|
||||
if(ShortModified())
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
//--- no opened position identified
|
||||
else
|
||||
{
|
||||
//--- check for long position (BUY) possibility
|
||||
if(LongOpened())
|
||||
return(true);
|
||||
//--- check for short position (SELL) possibility
|
||||
if(ShortOpened())
|
||||
return(true);
|
||||
}
|
||||
//--- exit without position processing
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- create all necessary objects
|
||||
if(!ExtExpert.Init())
|
||||
return(INIT_FAILED);
|
||||
//--- secceed
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert new tick handling function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
static datetime limit_time=0; // last trade processing time + timeout
|
||||
//--- don't process if timeout
|
||||
if(TimeCurrent()>=limit_time)
|
||||
{
|
||||
//--- check for data
|
||||
if(Bars(Symbol(),Period())>2*InpMATrendPeriod)
|
||||
{
|
||||
//--- change limit time by timeout in seconds if processed
|
||||
if(ExtExpert.Processing())
|
||||
limit_time=TimeCurrent()+ExtTimeOut;
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,372 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Functions.mqh |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//--- custom function y=f(x,y)
|
||||
typedef double(*MathFunction)(double,double);
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| math functions |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnMathFunction
|
||||
{
|
||||
Peaks=0,
|
||||
Chomolungma=1,
|
||||
ClimberDream=2,
|
||||
Granite=3,
|
||||
Hedgehog=4,
|
||||
Hill=5,
|
||||
Josephine=6,
|
||||
Screw=7,
|
||||
DoubleScrew=8,
|
||||
MultiExtremalScrew=9,
|
||||
Sink=10,
|
||||
Skin=11,
|
||||
Trapfall=12,
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Names of the math functions |
|
||||
//+------------------------------------------------------------------+
|
||||
const string ExtFunctionsNames[]=
|
||||
{
|
||||
"Peaks",
|
||||
"Chomolungma",
|
||||
"Climber Dream",
|
||||
"Granite",
|
||||
"Hedgehog",
|
||||
"Hill",
|
||||
"Josephine",
|
||||
"Screw",
|
||||
"Double Screw",
|
||||
"Multi Extremal Screw",
|
||||
"Sinc",
|
||||
"Skin",
|
||||
"Trapfall"
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Peaks |
|
||||
//+------------------------------------------------------------------+
|
||||
double PeaksFunction(double x,double y)
|
||||
{
|
||||
double res = 3*MathPow((1-x),2)*MathExp(-x*x-(y+1)*(y+1))-10*(0.2*x-MathPow(x,3)-MathPow(y,5))*MathExp(-x*x-y*y)-1/3*MathExp(-(x+1)*(x+1)-y*y);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Chomolungma |
|
||||
//+------------------------------------------------------------------+
|
||||
double ChomolungmaFunction(double x,double y)
|
||||
{
|
||||
double a= MathCos(x*x)+MathCos(y*y);
|
||||
double b= MathPow(MathCos(5*x*y),5);
|
||||
double c=1.0/MathPow(2,b);
|
||||
//--- calculate result
|
||||
double res=a-c;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function ClimberDream |
|
||||
//+------------------------------------------------------------------+
|
||||
double ClimberDreamFunction(double x,double y)
|
||||
{
|
||||
double a= MathSin(MathSqrt(MathAbs(x - 1.3) + MathAbs(y)));
|
||||
double b= MathCos(MathSqrt(MathAbs(MathSin(x))) + MathSqrt(MathAbs(MathSin(y))));
|
||||
double f=a+b;
|
||||
//--- calculate result
|
||||
double res=MathPow(f,4);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Granite |
|
||||
//+------------------------------------------------------------------+
|
||||
double GraniteFunction(double x,double y)
|
||||
{
|
||||
double a= MathPow(MathSin(MathSqrt(MathAbs(x)+MathAbs(y))),2);
|
||||
double b= MathPow(MathCos(MathSqrt(MathAbs(x)+MathAbs(y))),2);
|
||||
//--- calculate result
|
||||
double res=a*b;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Hedgehog |
|
||||
//+------------------------------------------------------------------+
|
||||
double HedgehogFunction(double x,double y)
|
||||
{
|
||||
double a1=MathSin(MathSqrt(MathAbs(x-2)+MathAbs(y)));
|
||||
double a2=MathCos(MathSqrt(MathAbs(MathSin(x)))+MathSqrt(MathAbs(MathSin(y))));
|
||||
//--- calculate result
|
||||
double res=a1+a2;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Hill |
|
||||
//+------------------------------------------------------------------+
|
||||
double HillFunction(double x,double y)
|
||||
{
|
||||
//--- calculate result
|
||||
double res=MathExp(-x*x-y*y);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Josephine |
|
||||
//+------------------------------------------------------------------+
|
||||
double JosephineFunction(double x,double y)
|
||||
{
|
||||
double a= MathSin(MathPow(MathAbs(x)+MathAbs(y),0.5));
|
||||
double b= MathCos(MathPow(MathAbs(x),0.5)+MathPow(MathAbs(y),0.5));
|
||||
//--- calculate function
|
||||
double res=a+b;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Screw |
|
||||
//+------------------------------------------------------------------+
|
||||
double ScrewFunction(double x,double y)
|
||||
{
|
||||
double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI);
|
||||
double b=x*x+y*y;
|
||||
double f=MathSin(b+a);
|
||||
//--- calculate result
|
||||
double res=(f*f);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function DoubleScrew |
|
||||
//+------------------------------------------------------------------+
|
||||
double DoubleScrewFunction(double x,double y)
|
||||
{
|
||||
double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI);
|
||||
double b=x*x+y*y;
|
||||
double res1=MathCos(b/2+a*3);
|
||||
res1=((res1*res1)/sqrt(b+1)-0.2);
|
||||
double res2=MathCos(b/2-a*3);
|
||||
res2=((res2*res2)/sqrt(b+1)-0.2);
|
||||
double f=fmax(res1,res2);
|
||||
//--- calculate result
|
||||
double res=(f>0)?f:0;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function MultiExtremalScrew |
|
||||
//+------------------------------------------------------------------+
|
||||
double MultiExtremalScrewFunction(double x,double y)
|
||||
{
|
||||
double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI);
|
||||
double b=x*x+y*y;
|
||||
double res1=MathCos(b/2+a*3);
|
||||
res1=((res1*res1)/sqrt(b+1)-0.2);
|
||||
double res2=MathCos(b/2-a*3);
|
||||
res2=((res2*res2)/sqrt(b+1)-0.2);
|
||||
//--- calculate function
|
||||
double res=fmin(res1,res2);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Sink |
|
||||
//+------------------------------------------------------------------+
|
||||
double SinkFunction(double x,double y)
|
||||
{
|
||||
static double k=5.0;
|
||||
static double p=6.0;
|
||||
//--- calculate result
|
||||
double res=MathSin(x*x+y*y)+k*MathExp(-p*x*x-p*y*y);
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Skin |
|
||||
//+------------------------------------------------------------------+
|
||||
double SkinFunction(double x,double y)
|
||||
{
|
||||
double a1=2*x*x;
|
||||
double a2=2*y*y;
|
||||
double b1=MathCos(a1)-1.1;
|
||||
b1=b1*b1;
|
||||
double c1=MathSin(0.5*x)-1.2;
|
||||
c1=c1*c1;
|
||||
double d1=MathCos(a2)-1.1;
|
||||
d1=d1*d1;
|
||||
double e1=MathSin(0.5*y)-1.2;
|
||||
e1=e1*e1;
|
||||
//--- calculate result
|
||||
double res=b1+c1-d1+e1;
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function Trapfall |
|
||||
//+------------------------------------------------------------------+
|
||||
double TrapfallFunction(double x,double y)
|
||||
{
|
||||
double a1=MathSqrt(MathAbs(MathSin(x-1.0)));
|
||||
double b1=MathSqrt(MathAbs(MathSin(y+2.0)));
|
||||
//--- calculate result
|
||||
double res=-MathSqrt(MathAbs(MathSin(MathSin(a1+b1))));
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| GenerateFunctionData |
|
||||
//+------------------------------------------------------------------+
|
||||
void GenerateFunctionData(double &data[],int &x_size,int &y_size,double x_min,double x_max,double y_min,double y_max,MathFunction function)
|
||||
{
|
||||
double dx = 0.1;
|
||||
double dy = 0.1;
|
||||
//---
|
||||
x_size = (int)((x_max - x_min)/dx) + 1;
|
||||
y_size = (int)((y_max - y_min)/dy) + 1;
|
||||
ArrayResize(data,x_size*y_size);
|
||||
//---
|
||||
for(int j = 0; j < y_size; j++)
|
||||
{
|
||||
for(int i = 0; i < x_size; i++)
|
||||
{
|
||||
double x = x_min + i*dx;
|
||||
double y = y_min + j*dy;
|
||||
data[j*x_size + i] = function(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| GenerateData |
|
||||
//+------------------------------------------------------------------+
|
||||
void GenerateData(EnMathFunction function_id,double &data[],int &x_size,int &y_size)
|
||||
{
|
||||
//---
|
||||
switch(function_id)
|
||||
{
|
||||
case Peaks:
|
||||
GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,PeaksFunction);
|
||||
break;
|
||||
case Chomolungma:
|
||||
GenerateFunctionData(data,x_size,y_size,-2.0,+2.0,-2.0,+2.0,ChomolungmaFunction);
|
||||
break;
|
||||
case ClimberDream:
|
||||
GenerateFunctionData(data,x_size,y_size,-10.0,+10.0,-10.0,+10.0,ClimberDreamFunction);
|
||||
break;
|
||||
case Granite:
|
||||
GenerateFunctionData(data,x_size,y_size,-4.0,+4.0,-4.0,+4.0,GraniteFunction);
|
||||
break;
|
||||
case Hedgehog:
|
||||
GenerateFunctionData(data,x_size,y_size,-10.0,+10.0,-10.0,+10.0,HedgehogFunction);
|
||||
break;
|
||||
case Hill:
|
||||
GenerateFunctionData(data,x_size,y_size,-1.5,+1.5,-1.5,+1.5,HillFunction);
|
||||
break;
|
||||
case Josephine:
|
||||
GenerateFunctionData(data,x_size,y_size,-200.0,+200.0,-200.0,+200.0,JosephineFunction);
|
||||
break;
|
||||
case Screw:
|
||||
GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,ScrewFunction);
|
||||
break;
|
||||
case DoubleScrew:
|
||||
GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,DoubleScrewFunction);
|
||||
break;
|
||||
case MultiExtremalScrew:
|
||||
GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,MultiExtremalScrewFunction);
|
||||
break;
|
||||
case Sink:
|
||||
GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,SinkFunction);
|
||||
break;
|
||||
case Skin:
|
||||
GenerateFunctionData(data,x_size,y_size,-5.0,+5.0,-5.0,+5.0,SkinFunction);
|
||||
break;
|
||||
case Trapfall:
|
||||
GenerateFunctionData(data,x_size,y_size,-5.0,+5.0,-5.0,+5.0,TrapfallFunction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| GenerateFunctionDataFixedSize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool GenerateFunctionDataFixedSize(int x_size,int y_size,double &data[],double x_min,double x_max,double y_min,double y_max,MathFunction function)
|
||||
{
|
||||
if(x_size<2 || y_size<2)
|
||||
{
|
||||
PrintFormat("Error in data sizes: x_size=%d,y_size=%d",x_size,y_size);
|
||||
return(false);
|
||||
}
|
||||
double dx = (x_max - x_min)/(x_size-1);
|
||||
double dy = (y_max - y_min)/(y_size-1);
|
||||
ArrayResize(data,x_size*y_size);
|
||||
//---
|
||||
for(int j = 0; j < y_size; j++)
|
||||
{
|
||||
for(int i = 0; i < x_size; i++)
|
||||
{
|
||||
double x = x_min + i*dx;
|
||||
double y = y_min + j*dy;
|
||||
data[j*x_size + i] = function(x,y);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| GenerateDataFixedSize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool GenerateDataFixedSize(int x_size,int y_size,EnMathFunction function_id,double &data[])
|
||||
{
|
||||
if(x_size<2 || y_size<2)
|
||||
{
|
||||
PrintFormat("Error in data sizes: x_size=%d,y_size=%d",x_size,y_size);
|
||||
return(false);
|
||||
}
|
||||
bool result=false;
|
||||
//---
|
||||
switch(function_id)
|
||||
{
|
||||
case Peaks:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,PeaksFunction);
|
||||
break;
|
||||
case Chomolungma:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-2.0,+2.0,-2.0,+2.0,ChomolungmaFunction);
|
||||
break;
|
||||
case ClimberDream:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-10.0,+10.0,-10.0,+10.0,ClimberDreamFunction);
|
||||
break;
|
||||
case Granite:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-4.0,+4.0,-4.0,+4.0,GraniteFunction);
|
||||
break;
|
||||
case Hedgehog:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-10.0,+10.0,-10.0,+10.0,HedgehogFunction);
|
||||
break;
|
||||
case Hill:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-1.5,+1.5,-1.5,+1.5,HillFunction);
|
||||
break;
|
||||
case Josephine:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-200.0,+200.0,-200.0,+200.0,JosephineFunction);
|
||||
break;
|
||||
case Screw:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,ScrewFunction);
|
||||
break;
|
||||
case DoubleScrew:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,DoubleScrewFunction);
|
||||
break;
|
||||
case MultiExtremalScrew:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,MultiExtremalScrewFunction);
|
||||
break;
|
||||
case Sink:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,SinkFunction);
|
||||
break;
|
||||
case Skin:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-5.0,+5.0,-5.0,+5.0,SkinFunction);
|
||||
break;
|
||||
case Trapfall:
|
||||
result=GenerateFunctionDataFixedSize(x_size,y_size,data,-5.0,+5.0,-5.0,+5.0,TrapfallFunction);
|
||||
break;
|
||||
}
|
||||
//---
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,233 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving Averages.mq5 |
|
||||
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
input double MaximumRisk = 0.02; // Maximum Risk in percentage
|
||||
input double DecreaseFactor = 3; // Descrease factor
|
||||
input int MovingPeriod = 12; // Moving Average period
|
||||
input int MovingShift = 6; // Moving Average shift
|
||||
//---
|
||||
int ExtHandle=0;
|
||||
bool ExtHedging=false;
|
||||
CTrade ExtTrade;
|
||||
|
||||
#define MA_MAGIC 1234501
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate optimal lot size |
|
||||
//+------------------------------------------------------------------+
|
||||
double TradeSizeOptimized(void)
|
||||
{
|
||||
double price=0.0;
|
||||
double margin=0.0;
|
||||
//--- select lot size
|
||||
if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price))
|
||||
return(0.0);
|
||||
if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin))
|
||||
return(0.0);
|
||||
if(margin<=0.0)
|
||||
return(0.0);
|
||||
|
||||
double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_MARGIN_FREE)*MaximumRisk/margin,2);
|
||||
//--- calculate number of losses orders without a break
|
||||
if(DecreaseFactor>0)
|
||||
{
|
||||
//--- select history for access
|
||||
HistorySelect(0,TimeCurrent());
|
||||
//---
|
||||
int orders=HistoryDealsTotal(); // total history deals
|
||||
int losses=0; // number of losses orders without a break
|
||||
|
||||
for(int i=orders-1;i>=0;i--)
|
||||
{
|
||||
ulong ticket=HistoryDealGetTicket(i);
|
||||
if(ticket==0)
|
||||
{
|
||||
Print("HistoryDealGetTicket failed, no trade history");
|
||||
break;
|
||||
}
|
||||
//--- check symbol
|
||||
if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol)
|
||||
continue;
|
||||
//--- check Expert Magic number
|
||||
if(HistoryDealGetInteger(ticket,DEAL_MAGIC)!=MA_MAGIC)
|
||||
continue;
|
||||
//--- check profit
|
||||
double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
|
||||
if(profit>0.0)
|
||||
break;
|
||||
if(profit<0.0)
|
||||
losses++;
|
||||
}
|
||||
//---
|
||||
if(losses>1)
|
||||
lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
|
||||
}
|
||||
//--- normalize and check limits
|
||||
double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
||||
lot=stepvol*NormalizeDouble(lot/stepvol,0);
|
||||
|
||||
double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
||||
if(lot<minvol)
|
||||
lot=minvol;
|
||||
|
||||
double maxvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
||||
if(lot>maxvol)
|
||||
lot=maxvol;
|
||||
//--- return trading volume
|
||||
return(lot);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for open position conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckForOpen(void)
|
||||
{
|
||||
MqlRates rt[2];
|
||||
//--- go trading only for first ticks of new bar
|
||||
if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
|
||||
{
|
||||
Print("CopyRates of ",_Symbol," failed, no history");
|
||||
return;
|
||||
}
|
||||
if(rt[1].tick_volume>1)
|
||||
return;
|
||||
//--- get current Moving Average
|
||||
double ma[1];
|
||||
if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
|
||||
{
|
||||
Print("CopyBuffer from iMA failed, no data");
|
||||
return;
|
||||
}
|
||||
//--- check signals
|
||||
ENUM_ORDER_TYPE signal=WRONG_VALUE;
|
||||
|
||||
if(rt[0].open>ma[0] && rt[0].close<ma[0])
|
||||
signal=ORDER_TYPE_SELL; // sell conditions
|
||||
else
|
||||
{
|
||||
if(rt[0].open<ma[0] && rt[0].close>ma[0])
|
||||
signal=ORDER_TYPE_BUY; // buy conditions
|
||||
}
|
||||
//--- additional checking
|
||||
if(signal!=WRONG_VALUE)
|
||||
{
|
||||
if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100)
|
||||
ExtTrade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),
|
||||
SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
|
||||
0,0);
|
||||
}
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for close position conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckForClose(void)
|
||||
{
|
||||
MqlRates rt[2];
|
||||
//--- go trading only for first ticks of new bar
|
||||
if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
|
||||
{
|
||||
Print("CopyRates of ",_Symbol," failed, no history");
|
||||
return;
|
||||
}
|
||||
if(rt[1].tick_volume>1)
|
||||
return;
|
||||
//--- get current Moving Average
|
||||
double ma[1];
|
||||
if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
|
||||
{
|
||||
Print("CopyBuffer from iMA failed, no data");
|
||||
return;
|
||||
}
|
||||
//--- positions already selected before
|
||||
bool signal=false;
|
||||
long type=PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if(type==(long)POSITION_TYPE_BUY && rt[0].open>ma[0] && rt[0].close<ma[0])
|
||||
signal=true;
|
||||
if(type==(long)POSITION_TYPE_SELL && rt[0].open<ma[0] && rt[0].close>ma[0])
|
||||
signal=true;
|
||||
//--- additional checking
|
||||
if(signal)
|
||||
{
|
||||
if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100)
|
||||
ExtTrade.PositionClose(_Symbol,3);
|
||||
}
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Position select depending on netting or hedging |
|
||||
//+------------------------------------------------------------------+
|
||||
bool SelectPosition()
|
||||
{
|
||||
bool res=false;
|
||||
//--- check position in Hedging mode
|
||||
if(ExtHedging)
|
||||
{
|
||||
uint total=PositionsTotal();
|
||||
for(uint i=0; i<total; i++)
|
||||
{
|
||||
string position_symbol=PositionGetSymbol(i);
|
||||
if(_Symbol==position_symbol && MA_MAGIC==PositionGetInteger(POSITION_MAGIC))
|
||||
{
|
||||
res=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- check position in Netting mode
|
||||
else
|
||||
{
|
||||
if(!PositionSelect(_Symbol))
|
||||
return(false);
|
||||
else
|
||||
return(PositionGetInteger(POSITION_MAGIC)==MA_MAGIC); //---check Magic number
|
||||
}
|
||||
//--- result for Hedging mode
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit(void)
|
||||
{
|
||||
//--- prepare trade class to control positions if hedging mode is active
|
||||
ExtHedging=((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
|
||||
ExtTrade.SetExpertMagicNumber(MA_MAGIC);
|
||||
ExtTrade.SetMarginMode();
|
||||
ExtTrade.SetTypeFillingBySymbol(Symbol());
|
||||
//--- Moving Average indicator
|
||||
ExtHandle=iMA(_Symbol,_Period,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE);
|
||||
if(ExtHandle==INVALID_HANDLE)
|
||||
{
|
||||
printf("Error creating MA indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- ok
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick(void)
|
||||
{
|
||||
//---
|
||||
if(SelectPosition())
|
||||
CheckForClose();
|
||||
else
|
||||
CheckForOpen();
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,657 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BlackCrows WhiteSoldiers CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodCCI =37; // CCI 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating CCI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check 3 Black Crows
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // long black
|
||||
(Open(2)-Close(2)>AvgBody(1)) &&
|
||||
(Open(1)-Close(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)<MidPoint(3)) && // lower midpoints
|
||||
(MidPoint(1)<MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\n3 Black Crows detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check 3 White Soldiers
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // long white
|
||||
(Close(2)-Open(2)>AvgBody(1)) &&
|
||||
(Close(1)-Open(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)>MidPoint(3)) && // higher midpoints
|
||||
(MidPoint(1)>MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\n3 White Soldiers detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,657 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BlackCrows WhiteSoldiers MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120200; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check 3 Black Crows
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // long black
|
||||
(Open(2)-Close(2)>AvgBody(1)) &&
|
||||
(Open(1)-Close(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)<MidPoint(3)) && // lower midpoints
|
||||
(MidPoint(1)<MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\n3 Black Crows detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check 3 White Soldiers
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // long white
|
||||
(Close(2)-Open(2)>AvgBody(1)) &&
|
||||
(Close(1)-Open(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)>MidPoint(3)) && // higher midpoints
|
||||
(MidPoint(1)>MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\n3 White Soldiers detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,657 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BlackCrows WhiteSoldiers RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check 3 Black Crows
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // long black
|
||||
(Open(2)-Close(2)>AvgBody(1)) &&
|
||||
(Open(1)-Close(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)<MidPoint(3)) && // lower midpoints
|
||||
(MidPoint(1)<MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\n3 Black Crows detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check 3 White Soldiers
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // long white
|
||||
(Close(2)-Open(2)>AvgBody(1)) &&
|
||||
(Close(1)-Open(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)>MidPoint(3)) && // higher midpoints
|
||||
(MidPoint(1)>MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\n3 White Soldiers detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,661 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BlackCrows WhiteSoldiers Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check 3 Black Crows
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // long black
|
||||
(Open(2)-Close(2)>AvgBody(1)) &&
|
||||
(Open(1)-Close(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)<MidPoint(3)) && // lower midpoints
|
||||
(MidPoint(1)<MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\n3 Black Crows detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check 3 White Soldiers
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // long white
|
||||
(Close(2)-Open(2)>AvgBody(1)) &&
|
||||
(Close(1)-Open(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)>MidPoint(3)) && // higher midpoints
|
||||
(MidPoint(1)>MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\n3 White Soldiers detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Engulfing CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodCCI =37; // CCI 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Engulfing
|
||||
if((Open(2)<Close(2)) && // previous candle is bearish
|
||||
(Open(1)-Close(1)>AvgBody(1)) && // body of the candle is higher than average value of the body
|
||||
(Close(1)<Open(2)) && // close price of the bearish candle is lower than open price of the bullish candle
|
||||
(MidOpenClose(2)>CloseAvg(2)) && // uptrend
|
||||
(Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Engulfing detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Engulfing
|
||||
if((Open(2)>Close(2)) && // previous candle is bearish
|
||||
(Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body
|
||||
(Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Close(2))) // open price of the bullish candle is lower than close price of the bearish
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Engulfing detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Engulfing MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120600; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Engulfing
|
||||
if((Open(2)<Close(2)) && // previous candle is bearish
|
||||
(Open(1)-Close(1)>AvgBody(1)) && // body of the candle is higher than average value of the body
|
||||
(Close(1)<Open(2)) && // close price of the bearish candle is lower than open price of the bullish candle
|
||||
(MidOpenClose(2)>CloseAvg(2)) && // uptrend
|
||||
(Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Engulfing detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Engulfing
|
||||
if((Open(2)>Close(2)) && // previous candle is bearish
|
||||
(Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body
|
||||
(Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Close(2))) // open price of the bullish candle is lower than close price of the bearish
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Engulfing detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Engulfing RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Engulfing
|
||||
if((Open(2)<Close(2)) && // previous candle is bearish
|
||||
(Open(1)-Close(1)>AvgBody(1)) && // body of the candle is higher than average value of the body
|
||||
(Close(1)<Open(2)) && // close price of the bearish candle is lower than open price of the bullish candle
|
||||
(MidOpenClose(2)>CloseAvg(2)) && // uptrend
|
||||
(Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Engulfing detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Engulfing
|
||||
if((Open(2)>Close(2)) && // previous candle is bearish
|
||||
(Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body
|
||||
(Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Close(2))) // open price of the bullish candle is lower than close price of the bearish
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Engulfing detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,688 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Engulfing Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow=13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Engulfing
|
||||
if((Open(2)<Close(2)) && // previous candle is bearish
|
||||
(Open(1)-Close(1)>AvgBody(1)) && // body of the candle is higher than average value of the body
|
||||
(Close(1)<Open(2)) && // close price of the bearish candle is lower than open price of the bullish candle
|
||||
(MidOpenClose(2)>CloseAvg(2)) && // uptrend
|
||||
(Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Engulfing detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Engulfing
|
||||
if((Open(2)>Close(2)) && // previous candle is bearish
|
||||
(Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body
|
||||
(Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Close(2))) // open price of the bullish candle is lower than close price of the bearish
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Engulfing detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Harami CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodCCI =37; // CCI 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=122100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Harami
|
||||
if((Close(1)<Open(1)) && // last completed bar is bearish (black day)
|
||||
((Close(2)-Open(2))>AvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white)
|
||||
(Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle
|
||||
(Open(1)<Close(2)) && // open price of the bearish candle is lower than close price of the bullish candle
|
||||
(MidPoint(2)>CloseAvg(2))) // up trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Harami detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Harami
|
||||
if((Close(1)>Open(1)) && // the last completed bar is bullish (white day)
|
||||
((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black)
|
||||
(Close(1)<Open(2)) && // close price of the bullish candle is lower than open price of the bearish candle
|
||||
(Open(1)>Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle
|
||||
(MidPoint(2)<CloseAvg(2))) // down trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Harami detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Harami MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121600; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Harami
|
||||
if((Close(1)<Open(1)) && // last completed bar is bearish (black day)
|
||||
((Close(2)-Open(2))>AvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white)
|
||||
(Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle
|
||||
(Open(1)<Close(2)) && // open price of the bearish candle is lower than close price of the bullish candle
|
||||
(MidPoint(2)>CloseAvg(2))) // up trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Harami detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Harami
|
||||
if((Close(1)>Open(1)) && // the last completed bar is bullish (white day)
|
||||
((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black)
|
||||
(Close(1)<Open(2)) && // close price of the bullish candle is lower than open price of the bearish candle
|
||||
(Open(1)>Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle
|
||||
(MidPoint(2)<CloseAvg(2))) // down trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Harami detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Harami RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Harami
|
||||
if((Close(1)<Open(1)) && // last completed bar is bearish (black day)
|
||||
((Close(2)-Open(2))>AvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white)
|
||||
(Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle
|
||||
(Open(1)<Close(2)) && // open price of the bearish candle is lower than close price of the bullish candle
|
||||
(MidPoint(2)>CloseAvg(2))) // up trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Harami detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Harami
|
||||
if((Close(1)>Open(1)) && // the last completed bar is bullish (white day)
|
||||
((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black)
|
||||
(Close(1)<Open(2)) && // close price of the bullish candle is lower than open price of the bearish candle
|
||||
(Open(1)>Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle
|
||||
(MidPoint(2)<CloseAvg(2))) // down trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Harami detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,685 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish Harami Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=122400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle =INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish Harami
|
||||
if((Close(1)<Open(1)) && // last completed bar is bearish (black day)
|
||||
((Close(2)-Open(2))>AvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white)
|
||||
(Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle
|
||||
(Open(1)<Close(2)) && // open price of the bearish candle is lower than close price of the bullish candle
|
||||
(MidPoint(2)>CloseAvg(2))) // up trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish Harami detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish Harami
|
||||
if((Close(1)>Open(1)) && // the last completed bar is bullish (white day)
|
||||
((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black)
|
||||
(Close(1)<Open(2)) && // close price of the bullish candle is lower than open price of the bearish candle
|
||||
(Open(1)>Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle
|
||||
(MidPoint(2)<CloseAvg(2))) // down trend
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish Harami detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,654 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish MeetingLines CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodCCI =37; // CCI 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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=123100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating CCI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish MeetingLines
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long white candle
|
||||
((Open(1)-Close(1))>AvgBody(1)) && // long black candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish MeetingLines detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish MeetingLines
|
||||
if((Open(2)-Close(2)>AvgBody(1)) && // long black candle
|
||||
((Close(1)-Open(1))>AvgBody(1)) && // long white candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish MeetingLines detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,652 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish MeetingLines MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=121200; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish MeetingLines
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long white candle
|
||||
((Open(1)-Close(1))>AvgBody(1)) && // long black candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish MeetingLines detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish MeetingLines
|
||||
if((Open(2)-Close(2)>AvgBody(1)) && // long black candle
|
||||
((Close(1)-Open(1))>AvgBody(1)) && // long white candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish MeetingLines detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,653 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish MeetingLines RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
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 =0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=122300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Bearish MeetingLines
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long white candle
|
||||
((Open(1)-Close(1))>AvgBody(1)) && // long black candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nBearish MeetingLines detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Bullish MeetingLines
|
||||
if((Open(2)-Close(2)>AvgBody(1)) && // long black candle
|
||||
((Close(1)-Open(1))>AvgBody(1)) && // long white candle
|
||||
(MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nBullish MeetingLines detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,662 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BullishBearish MeetingLines Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=123400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen=0; // Buy/Sell signal
|
||||
int ExtSignalClose=0; // signal to close a position
|
||||
string ExtPatternInfo=""; // current pattern information
|
||||
string ExtDirection=""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed=false; // pattern confirmed
|
||||
bool ExtCloseByTime=true; // requires closing by time
|
||||
bool ExtCheckPassed=true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check 3 Black Crows
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // long black
|
||||
(Open(2)-Close(2)>AvgBody(1)) &&
|
||||
(Open(1)-Close(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)<MidPoint(3)) && // lower midpoints
|
||||
(MidPoint(1)<MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\n3 Black Crows detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check 3 White Soldiers
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // long white
|
||||
(Close(2)-Open(2)>AvgBody(1)) &&
|
||||
(Close(1)-Open(1)>AvgBody(1)) &&
|
||||
(MidPoint(2)>MidPoint(3)) && // higher midpoints
|
||||
(MidPoint(1)>MidPoint(2)))
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\n3 White Soldiers detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,682 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DarkCloud PiercingLine CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodCCI =37; // CCI 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120500; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Dark Cloud Cover
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long body of the white candlestick (long white)
|
||||
(Close(1)<Close(2)) && // followed by a black candlestick
|
||||
(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)<Open(2)) && // of the previous candlestick (close inside previous body)
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Low(2))) // open lower than previous Low
|
||||
return(true);
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nPiercing Line detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,681 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DarkCloud PiercingLine MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=122600; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Dark Cloud Cover
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long body of the white candlestick (long white)
|
||||
(Close(1)<Close(2)) && // followed by a black candlestick
|
||||
(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)<Open(2)) && // of the previous candlestick (close inside previous body)
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Low(2))) // open lower than previous Low
|
||||
return(true);
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nPiercing Line detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,683 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DarkCloud PiercingLine RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120700; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Dark Cloud Cover
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long body of the white candlestick (long white)
|
||||
(Close(1)<Close(2)) && // followed by a black candlestick
|
||||
(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)<Open(2)) && // of the previous candlestick (close inside previous body)
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Low(2))) // open lower than previous Low
|
||||
return(true);
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nPiercing Line detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,687 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DarkCloud PiercingLine Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=120800; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Dark Cloud Cover
|
||||
if((Close(2)-Open(2)>AvgBody(1)) && // long body of the white candlestick (long white)
|
||||
(Close(1)<Close(2)) && // followed by a black candlestick
|
||||
(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)<Open(2)) && // of the previous candlestick (close inside previous body)
|
||||
(MidOpenClose(2)<CloseAvg(2)) && // downtrend
|
||||
(Open(1)<Low(2))) // open lower than previous Low
|
||||
return(true);
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nPiercing Line detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,679 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HangingMan Hammer CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodCCI =37; // CCI 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=124100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Hanging man
|
||||
if((MidPoint(1)>CloseAvg(2)) && // up trend
|
||||
(MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nHanging Man detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
//--- check Hammer
|
||||
if((MidPoint(1)<CloseAvg(2)) && // down trend
|
||||
(MathMin(Open(1), Close(1))>(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)<Close(2)) && (Open(1)<Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nHammer detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,679 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HangingMan Hammer MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=123600; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Hanging man
|
||||
if((MidPoint(1)>CloseAvg(2)) && // up trend
|
||||
(MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nHanging Man detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
//--- check Hammer
|
||||
if((MidPoint(1)<CloseAvg(2)) && // down trend
|
||||
(MathMin(Open(1), Close(1))>(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)<Close(2)) && (Open(1)<Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nHammer detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,677 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HangingMan Hammer RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=123300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Hanging man
|
||||
if((MidPoint(1)>CloseAvg(2)) && // up trend
|
||||
(MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nHanging Man detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Hammer
|
||||
if((MidPoint(1)<CloseAvg(2)) && // down trend
|
||||
(MathMin(Open(1), Close(1))>(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)<Close(2)) && (Open(1)<Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nHammer detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,683 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HangingMan Hammer Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpMAPeriod =5; // Trend MA period
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=124400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handles
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
int ExtTrendMAHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic 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)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Hanging man
|
||||
if((MidPoint(1)>CloseAvg(2)) && // up trend
|
||||
(MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nHanging Man detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
//--- check Hammer
|
||||
if((MidPoint(1)<CloseAvg(2)) && // down trend
|
||||
(MathMin(Open(1), Close(1))>(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3
|
||||
(Close(1)<Close(2)) && (Open(1)<Open(2))) // body gap
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nHammer detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic 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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,685 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MorningEvening StarDoji CCI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodCCI =37; // CCI 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=130100; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating CCI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Evening Doji
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Open(1)<Close(2)) && // down price gap on the last candlestick
|
||||
(Close(1)<Close(2))) // last candlestick close lower than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Doji detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Evening Star
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Close(1)<MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bullish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Star detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Doji
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Open(1)>Close(2)) && // upward price gap on the last candlestick
|
||||
(Close(1)>Close(2))) // last candlestick close higher than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Doji detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Star
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Close(1)>MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Star detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=CCI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<-50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI<-50";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>50))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: CCI>50";
|
||||
}
|
||||
|
||||
//--- 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(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80)))
|
||||
{
|
||||
//--- 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(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CCI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double CCI(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 CCI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,686 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MorningEvening StarDoji MFI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpPeriodMFI =37; // MFI period
|
||||
input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=130200; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating MFI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Evening Doji
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Open(1)<Close(2)) && // down price gap on the last candlestick
|
||||
(Close(1)<Close(2))) // last candlestick close lower than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Doji detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Evening Star
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Close(1)<MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bullish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Star detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Doji
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Open(1)>Close(2)) && // upward price gap on the last candlestick
|
||||
(Close(1)>Close(2))) // last candlestick close higher than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Doji detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Star
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Close(1)>MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Star detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=MFI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>60))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: MFI>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(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(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(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70)))
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| MFI indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MFI(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 MFI indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,686 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MorningEvening StarDoji RSI.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=130300; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Evening Doji
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Open(1)<Close(2)) && // down price gap on the last candlestick
|
||||
(Close(1)<Close(2))) // last candlestick close lower than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Doji detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Evening Star
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Close(1)<MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bullish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Star detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Doji
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Open(1)>Close(2)) && // upward price gap on the last candlestick
|
||||
(Close(1)>Close(2))) // last candlestick close higher than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Doji detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Star
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Close(1)>MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Star detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=RSI(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<40))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: RSI<40";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>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]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,691 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MorningEvening StarDoji Stoch.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Trade\SymbolInfo.mqh>
|
||||
|
||||
#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
|
||||
|
||||
//--- Input parameters
|
||||
input int InpAverBodyPeriod=12; // period for calculating average candlestick size
|
||||
input int InpStochK =47; // period %K
|
||||
input int InpStochD =9; // period %D
|
||||
input int InpStochSlow =13; // smoothing period %K
|
||||
input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type
|
||||
input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing 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=0.1; // lot
|
||||
//--- Expert ID
|
||||
input long InpMagicNumber=130400; // Magic Number
|
||||
|
||||
//--- global variables
|
||||
int ExtAvgBodyPeriod; // average candlestick calculation period
|
||||
int ExtSignalOpen =0; // Buy/Sell signal
|
||||
int ExtSignalClose =0; // signal to close a position
|
||||
string ExtPatternInfo =""; // current pattern information
|
||||
string ExtDirection =""; // position opening direction
|
||||
bool ExtPatternDetected=false; // pattern detected
|
||||
bool ExtConfirmed =false; // pattern confirmed
|
||||
bool ExtCloseByTime =true; // requires closing by time
|
||||
bool ExtCheckPassed =true; // status checking error
|
||||
//--- indicator handle
|
||||
int ExtIndicatorHandle=INVALID_HANDLE;
|
||||
|
||||
//--- service objects
|
||||
CTrade ExtTrade;
|
||||
CSymbolInfo ExtSymbolInfo;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
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=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied);
|
||||
if(ExtIndicatorHandle==INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating iStochastic indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
//--- OK
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- release indicator handle
|
||||
IndicatorRelease(ExtIndicatorHandle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- 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();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- if the position type does not match, move on to the next one
|
||||
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
if(check_type && (type!=search_type))
|
||||
continue;
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
string symbol =PositionGetString(POSITION_SYMBOL);
|
||||
long magic =PositionGetInteger(POSITION_MAGIC);
|
||||
//--- if they correspond to our values
|
||||
if(symbol==Symbol() && magic==InpMagicNumber)
|
||||
{
|
||||
//--- yes, this is the right position, stop the search
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- open position not found
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true if there are open positions with expired time |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExpiredByTimeExist()
|
||||
{
|
||||
//--- go through the list of all positions
|
||||
int positions=PositionsTotal();
|
||||
for(int i=0; i<positions; i++)
|
||||
{
|
||||
if(PositionGetTicket(i)!=0)
|
||||
{
|
||||
//--- get the name of the symbol and the expert id (magic number)
|
||||
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
|
||||
int check=BarsHold(open_time);
|
||||
//--- id the value is -1, the check completed with an error
|
||||
if(check==-1 || (BarsHold(open_time)>=(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_time<PeriodSeconds(_Period))
|
||||
{
|
||||
//--- opening time is inside the current bar
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
MqlRates bars[];
|
||||
if(CopyRates(_Symbol, _Period, open_time, TimeCurrent(), bars)==-1)
|
||||
{
|
||||
Print("Error. CopyRates() failed, error = ", GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
//--- check position holding time in bars
|
||||
return(ArraySize(bars));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the open price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Open(int index)
|
||||
{
|
||||
double val=iOpen(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the close price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Close(int index)
|
||||
{
|
||||
double val=iClose(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the low price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double Low(int index)
|
||||
{
|
||||
double val=iLow(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the high price of the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double High(int index)
|
||||
{
|
||||
double val=iHigh(_Symbol, _Period, index);
|
||||
//--- if the current check state was successful and an error was received
|
||||
if(ExtCheckPassed && val==0)
|
||||
ExtCheckPassed=false; // switch the status to failed
|
||||
|
||||
return(val);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle body price for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidPoint(int index)
|
||||
{
|
||||
return(High(index)+Low(index))/2.;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the middle price of the range for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double MidOpenClose(int index)
|
||||
{
|
||||
return((Open(index)+Close(index))/2.);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the average candlestick body size for the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double AvgBody(int index)
|
||||
{
|
||||
double sum=0;
|
||||
for(int i=index; i<index+ExtAvgBodyPeriod; i++)
|
||||
{
|
||||
sum+=MathAbs(Open(i)-Close(i));
|
||||
}
|
||||
return(sum/ExtAvgBodyPeriod);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful pattern check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPattern()
|
||||
{
|
||||
ExtPatternDetected=false;
|
||||
//--- check if there is a pattern
|
||||
ExtSignalOpen=SIGNAL_NOT;
|
||||
ExtPatternInfo="\r\nPattern not detected";
|
||||
ExtDirection="";
|
||||
|
||||
//--- check Evening Doji
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Open(1)<Close(2)) && // down price gap on the last candlestick
|
||||
(Close(1)<Close(2))) // last candlestick close lower than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Doji detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Evening Star
|
||||
if((Close(3)-Open(3)>AvgBody(1)) && // bullish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)>Close(3)) && // second candlestick close is higher than first candlestick close
|
||||
(Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open
|
||||
(Close(1)<MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bullish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_SELL;
|
||||
ExtPatternInfo="\r\nEvening Star detected";
|
||||
ExtDirection="Sell";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Doji
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.1) && // second candlestick body is doji (less than one tenth of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Open(1)>Close(2)) && // upward price gap on the last candlestick
|
||||
(Close(1)>Close(2))) // last candlestick close higher than second candlestick close
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Doji detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- check Morning Star
|
||||
if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average
|
||||
(MathAbs(Close(2)-Open(2))<AvgBody(1)*0.5) && // second candlestick body is short (less than a half of the average candle body)
|
||||
(Close(2)<Close(3)) && // second candlestick close is lower than first candlestick close
|
||||
(Open(2)<Open(3)) && // second candlestick open is lower than first candlestick open
|
||||
(Close(1)>MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one
|
||||
{
|
||||
ExtPatternDetected=true;
|
||||
ExtSignalOpen=SIGNAL_BUY;
|
||||
ExtPatternInfo="\r\nMorning Star detected";
|
||||
ExtDirection="Buy";
|
||||
return(true);
|
||||
}
|
||||
|
||||
//--- result of checking
|
||||
return(ExtCheckPassed);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns true in case of successful confirmation check |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckConfirmation()
|
||||
{
|
||||
ExtConfirmed=false;
|
||||
//--- if there is no pattern, do not search for confirmation
|
||||
if(!ExtPatternDetected)
|
||||
return(true);
|
||||
|
||||
//--- get the value of the stochastic indicator to confirm the signal
|
||||
double signal=StochSignal(1);
|
||||
if(signal==EMPTY_VALUE)
|
||||
{
|
||||
//--- failed to get indicator value, check failed
|
||||
return(false);
|
||||
}
|
||||
|
||||
//--- check the Buy signal
|
||||
if(ExtSignalOpen==SIGNAL_BUY && (signal<30))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal<30";
|
||||
}
|
||||
|
||||
//--- check the Sell signal
|
||||
if(ExtSignalOpen==SIGNAL_SELL && (signal>70))
|
||||
{
|
||||
ExtConfirmed=true;
|
||||
ExtPatternInfo+="\r\n Confirmed: StochSignal>70";
|
||||
}
|
||||
|
||||
//--- 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(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards
|
||||
((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards
|
||||
{
|
||||
//--- 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((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards
|
||||
((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards
|
||||
{
|
||||
//--- there is a signal to close a short position
|
||||
ExtSignalClose=CLOSE_SHORT;
|
||||
ExtDirection="Short";
|
||||
}
|
||||
|
||||
//--- successful completion of the check
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stochastic indicator value at the specified bar |
|
||||
//+------------------------------------------------------------------+
|
||||
double StochSignal(int index)
|
||||
{
|
||||
double indicator_values[];
|
||||
if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0)
|
||||
{
|
||||
//--- if the copying fails, report the error code
|
||||
PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError());
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
return(indicator_values[0]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user