add new backup ...
This commit is contained in:
@@ -0,0 +1,385 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCHttp
|
||||
// Description: provides all HTTP requirements ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// START Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
enum X_HTTP_METHOD
|
||||
{
|
||||
X_HTTP_GET,
|
||||
X_HTTP_POST
|
||||
};
|
||||
|
||||
//
|
||||
// Convert enum to String ...
|
||||
string ToString(X_HTTP_METHOD method)
|
||||
{
|
||||
//
|
||||
string result = "";
|
||||
|
||||
//
|
||||
switch (method)
|
||||
{
|
||||
//
|
||||
case X_HTTP_GET:
|
||||
result = "GET";
|
||||
break;
|
||||
|
||||
//
|
||||
case X_HTTP_POST:
|
||||
result = "POST";
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// END Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// Includes ...
|
||||
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||
|
||||
//
|
||||
// END Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// a Class for Manage Account ...
|
||||
class XSCHttp
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Constructor ...
|
||||
void XSCHttp()
|
||||
{
|
||||
XSCHttp("", 10000);
|
||||
}
|
||||
void XSCHttp(
|
||||
string path, // Base Folder to Store Data
|
||||
int timeout // base timeout for Requests
|
||||
)
|
||||
{
|
||||
//
|
||||
Path(path);
|
||||
Timeout(timeout);
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
void ~XSCHttp()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// START Getter(s)/Setter(s) ...
|
||||
//
|
||||
|
||||
//
|
||||
// Path ...
|
||||
void Path(string value)
|
||||
{
|
||||
mPath = value;
|
||||
}
|
||||
|
||||
string Path()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
//
|
||||
// Timeout ...
|
||||
void Timeout(int value)
|
||||
{
|
||||
mTimeout = value;
|
||||
}
|
||||
|
||||
//
|
||||
int Timeout()
|
||||
{
|
||||
return mTimeout;
|
||||
}
|
||||
|
||||
//
|
||||
// Error ...
|
||||
int Error()
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
||||
//
|
||||
// Response ...
|
||||
string Response()
|
||||
{
|
||||
return mResponse;
|
||||
}
|
||||
|
||||
//
|
||||
// END Getter(s)/Setter(s) ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Provided Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Send Global Request ...
|
||||
int SendRequest(
|
||||
X_HTTP_METHOD method, // Httm Request Method
|
||||
const string url, // Server Address
|
||||
const string headers, // Headers providing
|
||||
const char &payload[], // the Data which needs to Send
|
||||
char &response[], // Response of request
|
||||
string responseHeaders, // Response Headers
|
||||
int timeout = 500 // Timeout for response default is 500
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = -1;
|
||||
|
||||
//
|
||||
string strMethod = ToString(method);
|
||||
if (StringLen(strMethod) == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Reset State ...
|
||||
ResetState();
|
||||
|
||||
//
|
||||
result = WebRequest(
|
||||
strMethod,
|
||||
url,
|
||||
headers,
|
||||
timeout,
|
||||
payload,
|
||||
response,
|
||||
responseHeaders);
|
||||
|
||||
//
|
||||
if (result < 0)
|
||||
{
|
||||
mError = GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
mResponse = CharArrayToString(response);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Get Request ...
|
||||
int GetRequest(
|
||||
const string url, // Server Address
|
||||
const string headers, // Headers providing
|
||||
const char &payload[], // the Data which needs to Send
|
||||
char &response[], // Response of request
|
||||
string responseHeaders, // Response Headers
|
||||
int timeout = 500 // Timeout for response default is 500
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = SendRequest(
|
||||
X_HTTP_GET,
|
||||
url,
|
||||
headers,
|
||||
payload,
|
||||
response,
|
||||
responseHeaders,
|
||||
timeout);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Post Request ...
|
||||
int PostRequest(
|
||||
const string url, // Server Address
|
||||
const string headers, // Headers providing
|
||||
const char &payload[], // the Data which needs to Send
|
||||
char &response[], // Response of request
|
||||
string responseHeaders, // Response Headers
|
||||
int timeout = 500 // Timeout for response default is 500
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = SendRequest(
|
||||
X_HTTP_POST,
|
||||
url,
|
||||
headers,
|
||||
payload,
|
||||
response,
|
||||
responseHeaders,
|
||||
timeout);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Download Specific URL Content to Specific Path and File Name ...
|
||||
bool Download(
|
||||
string url, // the URL address which going to download
|
||||
string fileName // Specify Destination file name to Store Response
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
string filePath = GetFilePath(fileName);
|
||||
string cookie = NULL;
|
||||
string referer = NULL;
|
||||
int timeout = Timeout();
|
||||
|
||||
//
|
||||
char payload[];
|
||||
string headers;
|
||||
char response[];
|
||||
string responseHeaders;
|
||||
|
||||
//
|
||||
// Send Request ...
|
||||
int requestResult = GetRequest(
|
||||
url,
|
||||
headers,
|
||||
payload,
|
||||
response,
|
||||
responseHeaders,
|
||||
timeout);
|
||||
|
||||
//
|
||||
// Define File Handler ...
|
||||
int mFileHandler = FileOpen(
|
||||
filePath,
|
||||
FILE_WRITE | FILE_BIN);
|
||||
if (mFileHandler == INVALID_HANDLE)
|
||||
{
|
||||
//
|
||||
mError = GetLastError();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Write Response to File ...
|
||||
uint writed = FileWriteArray(
|
||||
mFileHandler,
|
||||
response,
|
||||
0,
|
||||
ArraySize(response));
|
||||
FileFlush(mFileHandler);
|
||||
FileClose(mFileHandler);
|
||||
|
||||
//
|
||||
result = writed > 0;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// END Provided Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Destintion Folder Path ...
|
||||
string mPath;
|
||||
|
||||
//
|
||||
// WEB Request Timeout Value ...
|
||||
int mTimeout;
|
||||
|
||||
//
|
||||
// WEB Request's Response ...
|
||||
string mResponse;
|
||||
|
||||
//
|
||||
// Error Value ...
|
||||
int mError;
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Reset Errors State ...
|
||||
void ResetState()
|
||||
{
|
||||
//
|
||||
// Reset Errors ...
|
||||
mError = -1;
|
||||
mResponse = "";
|
||||
ResetLastError();
|
||||
}
|
||||
|
||||
//
|
||||
// Generate Full File Path ...
|
||||
string GetFilePath(string fileName)
|
||||
{
|
||||
//
|
||||
string result = "";
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
Path() + "\\" + fileName
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// START Usefull Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Usefull Functions ...
|
||||
//
|
||||
@@ -0,0 +1,62 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSC121Provider
|
||||
// Description: a Market Analyser and Signal Provider
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// TODO:
|
||||
// - [] add XCT for Candle Timing ...
|
||||
// - [] add XCS for Candle Styling ...
|
||||
// - [] add Support for XZG Indicator ...
|
||||
// - [] implement XPV based on Market Cycles ...
|
||||
// - [] create XPV Helper class ...
|
||||
// - [] create XZG Helper class ...
|
||||
// - [] add Pivots Functionality based on XZG and XPV ...
|
||||
// - [] add File as Struct functionality and implement it ...
|
||||
// - [] add Support for OnSignal Event ...
|
||||
// - [] add support for Alerting ...
|
||||
// - [] Refactor XSignal:
|
||||
// -- [] Add support for Multiple TPS and Trailing Stops ...
|
||||
// -- [] Add support for Clean, Constructor and Init Functions on struct ...
|
||||
// -- [] Add support for Prepare Signal inside struct ...
|
||||
// -- [] Add Support for Position Management inside XTrade Class for Handling
|
||||
// Trail SL, or Partial Close Positions ...
|
||||
// -- [] Convert providers from Array to string ...
|
||||
// -- [] Add Support For Serializing and also Deseriallizing functionality ...
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
|
||||
//
|
||||
#include "../Classes/x-saherelm.x121.xmcycle.class.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// Configuration of X121 Provider ...
|
||||
struct X121ProviderInputs
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// Class ...
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,398 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCAccount
|
||||
// Description: provides all Account requirements ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// START Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// Includes ...
|
||||
#include <Trade/AccountInfo.mqh>
|
||||
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||
|
||||
//
|
||||
// END Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// a Class for Manage Account ...
|
||||
class XSCAccount
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Constructor ...
|
||||
void XSCAccount()
|
||||
{
|
||||
//
|
||||
mAccountInfo = new CAccountInfo();
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
void ~XSCAccount()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// START Provided Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// User Account ...
|
||||
long GetUserAccount()
|
||||
{
|
||||
return mAccountInfo.Login();
|
||||
}
|
||||
|
||||
//
|
||||
// Account Leverage ...
|
||||
long GetLeverage()
|
||||
{
|
||||
return mAccountInfo.Leverage();
|
||||
}
|
||||
|
||||
//
|
||||
// Get Trade Expert State ...
|
||||
bool CanExpertTrade()
|
||||
{
|
||||
return mAccountInfo.TradeExpert();
|
||||
}
|
||||
|
||||
//
|
||||
// User Account Trade Mopde (ENUM_ACCOUNT_TRADE_MODE) ...
|
||||
// --------------------------
|
||||
// ACCOUNT_TRADE_MODE_DEMO
|
||||
// ACCOUNT_TRADE_MODE_CONTEST
|
||||
// ACCOUNT_TRADE_MODE_REAL
|
||||
ENUM_ACCOUNT_TRADE_MODE GetTradeMode()
|
||||
{
|
||||
return mAccountInfo.TradeMode();
|
||||
}
|
||||
|
||||
//
|
||||
// Get Account Balance ...
|
||||
double GetBalance()
|
||||
{
|
||||
return mAccountInfo.Balance();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of give Credit ...
|
||||
double GetCredit()
|
||||
{
|
||||
return mAccountInfo.Credit();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of current Profit on account ...
|
||||
double GetProfit()
|
||||
{
|
||||
return mAccountInfo.Profit();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of current Equity on account ...
|
||||
double GetEquity()
|
||||
{
|
||||
return mAccountInfo.Equity();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of reserved Margin ...
|
||||
double GetMargin()
|
||||
{
|
||||
return mAccountInfo.Margin();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the amount of free Margin ...
|
||||
double GetFreeMargin()
|
||||
{
|
||||
return mAccountInfo.FreeMargin();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Level of Margin ...
|
||||
double GetMarginLevel()
|
||||
{
|
||||
return mAccountInfo.MarginLevel();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Level Of Margin for a Deposit ...
|
||||
double GetMarginCall()
|
||||
{
|
||||
return mAccountInfo.MarginCall();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Level of Margin for Stop out ...
|
||||
double GetMarginStopOut()
|
||||
{
|
||||
return mAccountInfo.MarginStopOut();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Client Name ...
|
||||
string GetName()
|
||||
{
|
||||
return mAccountInfo.Name();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Trade Server Name ...
|
||||
string GetServerName()
|
||||
{
|
||||
return mAccountInfo.Server();
|
||||
}
|
||||
|
||||
//
|
||||
// Get deposit Currency Name ...
|
||||
string GetCurrency()
|
||||
{
|
||||
return mAccountInfo.Currency();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Company Name that serves an Account ...
|
||||
string GetCompany()
|
||||
{
|
||||
return mAccountInfo.Company();
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Profits for the current account based on passed parameters ...
|
||||
double CalculateTradeProfit(
|
||||
const string symbol, // trading symbol
|
||||
ENUM_ORDER_TYPE type, // order type
|
||||
double volume, // volume
|
||||
double entry, // open price
|
||||
double exit // close price
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = mAccountInfo.OrderProfitCheck(
|
||||
symbol,
|
||||
type,
|
||||
volume,
|
||||
entry,
|
||||
exit);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate amount of margin which required for trade operation ...
|
||||
double CalculateMarging(
|
||||
const string symbol, // trading symbol
|
||||
ENUM_ORDER_TYPE type, // order type
|
||||
double volume, // volume
|
||||
double entry // open price
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = mAccountInfo.MarginCheck(
|
||||
symbol,
|
||||
type,
|
||||
volume,
|
||||
entry);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate amount of free margin left after trade operation ...
|
||||
double CalculateFreeMarging(
|
||||
const string symbol, // trading symbol
|
||||
ENUM_ORDER_TYPE type, // order type
|
||||
double volume, // volume
|
||||
double entry // open price
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = mAccountInfo.FreeMarginCheck(
|
||||
symbol,
|
||||
type,
|
||||
volume,
|
||||
entry);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the Maximum possible volume of trade operation ...
|
||||
double CalculateMaxVolume(
|
||||
const string symbol, // trading symbol
|
||||
ENUM_ORDER_TYPE type, // order type
|
||||
double entry, // open price
|
||||
double percent = 100 // percent of available margin
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = mAccountInfo.MaxLotCheck(
|
||||
symbol,
|
||||
type,
|
||||
entry,
|
||||
percent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Point Value for Given Symbol based on Account ...
|
||||
double GetPointValue(
|
||||
string symbol // trading symbol
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
||||
|
||||
//
|
||||
double ticksPerPoint = tickSize / point;
|
||||
|
||||
//
|
||||
result = tickValue / ticksPerPoint;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Risk Amount based on account Currency by Providing:
|
||||
// Points and Volume ...
|
||||
double CalculateRiskAmount(
|
||||
string symbol, // trading symbol
|
||||
double points, // amount of Risk Points
|
||||
double volume // position Volume
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
double pointValue = GetPointValue(symbol);
|
||||
|
||||
//
|
||||
result = pointValue * volume * points;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Risk Points based on account Currency by Providing:
|
||||
// Volume and Amount ...
|
||||
double CalculateRiskPoints(
|
||||
string symbol, // trading symbol
|
||||
double volume, // position Volume
|
||||
double amount // amount of Risk based on Account Currency
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
double pointValue = GetPointValue(symbol);
|
||||
|
||||
//
|
||||
result = amount / (pointValue * volume);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Volume based on account Currency by Providing:
|
||||
// Amount and Risk Points ...
|
||||
double CalculateVolume(
|
||||
string symbol, // trading symbol
|
||||
double amount, // amount of Risk based on Account Currency
|
||||
double points // amount of Risk Points
|
||||
)
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
points =
|
||||
points <= 0
|
||||
? 10
|
||||
: points;
|
||||
|
||||
//
|
||||
double pointValue = GetPointValue(symbol);
|
||||
|
||||
//
|
||||
result = amount / (pointValue * points);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// END Provided Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Account Info ...
|
||||
CAccountInfo mAccountInfo;
|
||||
};
|
||||
|
||||
//
|
||||
// START Usefull Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Usefull Functions ...
|
||||
//
|
||||
Binary file not shown.
@@ -0,0 +1,444 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCDataCollector
|
||||
// Description: provides Data Collection Requirements ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
class XSCDataCollector
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
// Constructors ...
|
||||
void XSCDataCollector(
|
||||
string path = NULL, // Base Folder for Data Store
|
||||
string fileName = NULL // File Name for Data Store
|
||||
)
|
||||
{
|
||||
//
|
||||
if (!IsValid(path))
|
||||
{
|
||||
path = GetType();
|
||||
}
|
||||
|
||||
//
|
||||
if (!IsValid(fileName))
|
||||
{
|
||||
fileName = GetType() + ".txt";
|
||||
}
|
||||
|
||||
//
|
||||
Path(path);
|
||||
FileName(fileName);
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
void ~XSCDataCollector() {}
|
||||
|
||||
//
|
||||
// Properties ...
|
||||
|
||||
//
|
||||
bool Path(string value)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = IsValid(value);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = value != mPath;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
mPath = value;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
string Path()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
//
|
||||
bool FileName(string value)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = IsValid(value);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = value != mFileName;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
mFileName = value;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
string FileName()
|
||||
{
|
||||
return mFileName;
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Clear Exists Collected Data ...
|
||||
void Clear()
|
||||
{
|
||||
//
|
||||
ResetLastError();
|
||||
|
||||
//
|
||||
string dataStorePath = GetStorePath();
|
||||
|
||||
//
|
||||
// Check Data Store Exists or not ...
|
||||
bool isExists = FileIsExist(dataStorePath);
|
||||
if (!isExists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
FileDelete(dataStorePath);
|
||||
}
|
||||
|
||||
//
|
||||
// Collect All Stored Items ...
|
||||
int Collect(
|
||||
T &items[] // Hold Result
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
Clean(items);
|
||||
|
||||
//
|
||||
// Reading Store Whole Content ...
|
||||
|
||||
//
|
||||
string storePath = GetStorePath();
|
||||
int mFileHandler = FileOpen(
|
||||
storePath,
|
||||
FILE_READ | FILE_TXT);
|
||||
result = mFileHandler != INVALID_HANDLE;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse Store Content and Read Data ...
|
||||
while (!FileIsEnding(mFileHandler))
|
||||
{
|
||||
//
|
||||
// Each Line Represent One Model ...
|
||||
string content = FileReadString(mFileHandler);
|
||||
|
||||
//
|
||||
T iItem;
|
||||
bool isValid = iItem.Parse(content);
|
||||
if (isValid)
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
iItem,
|
||||
items
|
||||
//
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Close File ...
|
||||
FileClose(mFileHandler);
|
||||
|
||||
//
|
||||
result = ArraySize(items);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Add Item ...
|
||||
bool Add(
|
||||
T &item // Item to Store
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = item.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
string content = item.ToString();
|
||||
result = IsValid(content);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
string storePath = GetStorePath();
|
||||
int mFileHandler = FileOpen(
|
||||
storePath,
|
||||
FILE_READ | FILE_WRITE | FILE_TXT);
|
||||
result = mFileHandler != INVALID_HANDLE;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
FileSeek(mFileHandler, 0, SEEK_END);
|
||||
FileWrite(mFileHandler, content);
|
||||
FileFlush(mFileHandler);
|
||||
FileClose(mFileHandler);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Add Items ...
|
||||
int Add(
|
||||
T &items[] // Items to Add ...
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
int itemsCount = ArraySize(items);
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
T iItem = items[i];
|
||||
|
||||
//
|
||||
if (!iItem.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
bool isAdded = Add(iItem);
|
||||
if (isAdded)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove Item ...
|
||||
bool Remove(
|
||||
T &item // Item to Remove
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = item.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
T items[];
|
||||
int itemsCount = Collect(items);
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int itemIndex = item.FindIndex(items);
|
||||
result = ArrayRemove(
|
||||
items,
|
||||
itemIndex,
|
||||
1);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
Clear();
|
||||
|
||||
//
|
||||
int itemsAdded = Add(items);
|
||||
|
||||
//
|
||||
result = itemsAdded == ArraySize(items);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Retrieve Type of Class as String ...
|
||||
string GetType()
|
||||
{
|
||||
//
|
||||
string mType = (string) typename(T);
|
||||
|
||||
//
|
||||
string result = mType;
|
||||
|
||||
//
|
||||
string parts[];
|
||||
int partsCount = SplitContent(
|
||||
parts,
|
||||
result,
|
||||
" "
|
||||
//
|
||||
);
|
||||
if (partsCount <= 0)
|
||||
{
|
||||
//
|
||||
result = mType;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool hasLastPart = GetLastItem(
|
||||
result,
|
||||
parts
|
||||
//
|
||||
);
|
||||
if (!hasLastPart)
|
||||
{
|
||||
//
|
||||
result = mType;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Pricate ...
|
||||
private:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
string mPath; // Path
|
||||
string mFileName; // Data Store File Name
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Generate Full File Path ...
|
||||
string GetFilePath(string fileName)
|
||||
{
|
||||
//
|
||||
string result = "";
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
Path() + "\\" + fileName
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Data Store File Address ...
|
||||
string GetStorePath()
|
||||
{
|
||||
//
|
||||
string result = NULL;
|
||||
|
||||
//
|
||||
result = GetFilePath(mFileName);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCBaseHelper
|
||||
// Description: provides all Base Indicator
|
||||
// Helper requirements ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Includes ...
|
||||
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// a Class for Handle base requirements ...
|
||||
// for indicators ...
|
||||
class XSCBaseHelper
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Constructor ...
|
||||
void XSCBaseHelper(
|
||||
string symbol, // Trading Symbol
|
||||
ENUM_TIMEFRAMES period // Trading Time Frame
|
||||
)
|
||||
{
|
||||
//
|
||||
mSymbol = symbol;
|
||||
mPeriod = period;
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
void ~XSCBaseHelper()
|
||||
{
|
||||
//
|
||||
IndicatorRelease(mHandler);
|
||||
}
|
||||
|
||||
//
|
||||
// Setter(s) / Getter(s) ...
|
||||
|
||||
//
|
||||
// Symbol ...
|
||||
string GetSymbol()
|
||||
{
|
||||
return mSymbol;
|
||||
}
|
||||
|
||||
//
|
||||
// Period ...
|
||||
ENUM_TIMEFRAMES GetPeriod()
|
||||
{
|
||||
return mPeriod;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Bars ...
|
||||
int CountBars()
|
||||
{
|
||||
//
|
||||
int result =
|
||||
Bars(
|
||||
mSymbol,
|
||||
mPeriod);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int CountCalculatedBars()
|
||||
{
|
||||
return BarsCalculated(mHandler);
|
||||
}
|
||||
|
||||
//
|
||||
// Functions ...
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
// Symbol ...
|
||||
string mSymbol;
|
||||
|
||||
//
|
||||
// Period ...
|
||||
ENUM_TIMEFRAMES mPeriod;
|
||||
|
||||
//
|
||||
// Indicator Handler ...
|
||||
int mHandler;
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
};
|
||||
|
||||
//
|
||||
// Tools ....
|
||||
Binary file not shown.
@@ -0,0 +1,441 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCMD5
|
||||
// Description: Provides MD5 Hashing Requirements ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// START Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
static uchar _md5_PADDING[64] =
|
||||
{
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
//
|
||||
#define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define _md5_H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define _md5_I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
#define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
//
|
||||
#define _md5_FF(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += _md5_F((b), (c), (d)) + (x) + (uint)(ac); \
|
||||
(a) = _md5_ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
//
|
||||
#define _md5_GG(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += _md5_G((b), (c), (d)) + (x) + (uint)(ac); \
|
||||
(a) = _md5_ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
//
|
||||
#define _md5_HH(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += _md5_H((b), (c), (d)) + (x) + (uint)(ac); \
|
||||
(a) = _md5_ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
//
|
||||
#define _md5_II(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += _md5_I((b), (c), (d)) + (x) + (uint)(ac); \
|
||||
(a) = _md5_ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
//
|
||||
#define _md5_INIT_STATE_0 0x67452301
|
||||
#define _md5_INIT_STATE_1 0xefcdab89
|
||||
#define _md5_INIT_STATE_2 0x98badcfe
|
||||
#define _md5_INIT_STATE_3 0x10325476
|
||||
|
||||
//
|
||||
#define _md5_S11 7
|
||||
#define _md5_S12 12
|
||||
#define _md5_S13 17
|
||||
#define _md5_S14 22
|
||||
|
||||
//
|
||||
#define _md5_S21 5
|
||||
#define _md5_S22 9
|
||||
#define _md5_S23 14
|
||||
#define _md5_S24 20
|
||||
|
||||
//
|
||||
#define _md5_S31 4
|
||||
#define _md5_S32 11
|
||||
#define _md5_S33 16
|
||||
#define _md5_S34 23
|
||||
|
||||
//
|
||||
#define _md5_S41 6
|
||||
#define _md5_S42 10
|
||||
#define _md5_S43 15
|
||||
#define _md5_S44 21
|
||||
|
||||
//
|
||||
// END Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// XCMD5 a library for Hashing ...
|
||||
class XSCMD5
|
||||
{
|
||||
//
|
||||
// Public Provides ...
|
||||
public:
|
||||
//
|
||||
// Protected Provides ...
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XSCMD5(void) {}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XSCMD5(void) {}
|
||||
|
||||
//
|
||||
// Hash Specified Char Array ...
|
||||
string Hash(
|
||||
uchar &mSource[], // Specify Char Array to Hash
|
||||
int mLength = 0 // Specify Length of Char Array which required to hash
|
||||
)
|
||||
{
|
||||
//
|
||||
string result = "";
|
||||
|
||||
//
|
||||
int sourceCount = ArraySize(mSource);
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
sourceCount <= 0 ||
|
||||
(sourceCount > 0 && mLength > sourceCount))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Args ...
|
||||
if (mLength == 0)
|
||||
{
|
||||
mLength = sourceCount;
|
||||
}
|
||||
|
||||
//
|
||||
// Init MD5 ...
|
||||
MD5Init();
|
||||
|
||||
//
|
||||
// Update Buffer ...
|
||||
MD5Update(mSource, mLength);
|
||||
|
||||
//
|
||||
// Calculate Result ...
|
||||
result = MD5Final();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Hash Specified String ...
|
||||
string Hash(
|
||||
string mSource // Specified String
|
||||
)
|
||||
{
|
||||
//
|
||||
string result = "";
|
||||
|
||||
//
|
||||
// Converts String to Char Array ...
|
||||
uchar bytes[];
|
||||
StringToCharArray(
|
||||
mSource,
|
||||
bytes,
|
||||
0,
|
||||
StringLen(mSource));
|
||||
|
||||
//
|
||||
result = Hash(
|
||||
bytes,
|
||||
ArraySize(bytes));
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
//
|
||||
// Private Provides ...
|
||||
private:
|
||||
//
|
||||
uint m_lMD5[4];
|
||||
uint m_nCount[2];
|
||||
uchar m_lpszBuffer[64];
|
||||
|
||||
//
|
||||
// Convert Byte to DWord ...
|
||||
void ByteToDWord(int &out[], uint &in[], uint len)
|
||||
{
|
||||
//
|
||||
uint i = 0;
|
||||
uint j = 0;
|
||||
|
||||
//
|
||||
for (; j < len; i++, j += 4)
|
||||
{
|
||||
out[i] = (int)in[j] | (int)in[j + 1] << 8 | (int)in[j + 2] << 16 | (int)in[j + 3] << 24;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Convert DWord to Byte ...
|
||||
void DWordToByte(uchar &out[], int &in[], uint len)
|
||||
{
|
||||
//
|
||||
uint i = 0;
|
||||
uint j = 0;
|
||||
|
||||
//
|
||||
for (; j < len; i++, j += 4)
|
||||
{
|
||||
//
|
||||
out[j] = (uchar)(in[i] & 0xff);
|
||||
out[j + 1] = (uchar)((in[i] >> 8) & 0xff);
|
||||
out[j + 2] = (uchar)((in[i] >> 16) & 0xff);
|
||||
out[j + 3] = (uchar)((in[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Init MD5 Array ...
|
||||
void MD5Init()
|
||||
{
|
||||
//
|
||||
ArrayInitialize(m_lpszBuffer, 64);
|
||||
|
||||
//
|
||||
m_nCount[0] = m_nCount[1] = 0;
|
||||
m_lMD5[0] = _md5_INIT_STATE_0;
|
||||
m_lMD5[1] = _md5_INIT_STATE_1;
|
||||
m_lMD5[2] = _md5_INIT_STATE_2;
|
||||
m_lMD5[3] = _md5_INIT_STATE_3;
|
||||
}
|
||||
|
||||
//
|
||||
// Update MD5 ...
|
||||
void MD5Update(uchar &inBuf[], uint inLen)
|
||||
{
|
||||
//
|
||||
int i, ii;
|
||||
int mdi;
|
||||
|
||||
//
|
||||
uint in[16];
|
||||
int i0 = 0;
|
||||
|
||||
//
|
||||
mdi = (int)((m_nCount[0] >> 3) & 0x3F);
|
||||
|
||||
//
|
||||
if ((m_nCount[0] + ((uint)inLen << 3)) < m_nCount[0])
|
||||
{
|
||||
m_nCount[1]++;
|
||||
}
|
||||
|
||||
//
|
||||
m_nCount[0] += ((uint)inLen << 3);
|
||||
m_nCount[1] += ((uint)inLen >> 29);
|
||||
|
||||
//
|
||||
while ((inLen--) > 0)
|
||||
{
|
||||
//
|
||||
m_lpszBuffer[mdi++] = inBuf[i0++];
|
||||
if (mdi == 0x40)
|
||||
{
|
||||
//
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4)
|
||||
{
|
||||
in[i] = (((uint)m_lpszBuffer[ii + 3]) << 24) | (((uint)m_lpszBuffer[ii + 2]) << 16) | (((uint)m_lpszBuffer[ii + 1]) << 8) | ((uint)m_lpszBuffer[ii]);
|
||||
}
|
||||
|
||||
//
|
||||
Transform(m_lMD5, in);
|
||||
|
||||
//
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Finalize an MD5 Expression ...
|
||||
string MD5Final()
|
||||
{
|
||||
//
|
||||
uchar bits[8];
|
||||
int nIndex;
|
||||
uint nPadLen;
|
||||
const int nMD5Size = 16;
|
||||
uchar lpszMD5[16];
|
||||
string temp;
|
||||
string out = "";
|
||||
int i;
|
||||
|
||||
//
|
||||
DWordToByte(bits, m_nCount, 8);
|
||||
nIndex = (int)((m_nCount[0] >> 3) & 0x3f);
|
||||
nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
|
||||
MD5Update(_md5_PADDING, nPadLen);
|
||||
MD5Update(bits, 8);
|
||||
DWordToByte(lpszMD5, m_lMD5, nMD5Size);
|
||||
|
||||
//
|
||||
for (i = 0; i < nMD5Size; i++)
|
||||
{
|
||||
//
|
||||
if (lpszMD5[i] == 0)
|
||||
{
|
||||
temp = "00";
|
||||
}
|
||||
else if (lpszMD5[i] <= 15)
|
||||
{
|
||||
temp = StringFormat("0%x", lpszMD5[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = StringFormat("%x", lpszMD5[i]);
|
||||
}
|
||||
|
||||
//
|
||||
out += temp;
|
||||
}
|
||||
|
||||
//
|
||||
lpszMD5[0] = '\0';
|
||||
|
||||
//
|
||||
return (out);
|
||||
}
|
||||
|
||||
//
|
||||
// Transform Buffers ...
|
||||
void Transform(uint &buf[], uint &in[])
|
||||
{
|
||||
//
|
||||
uint a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
//
|
||||
_md5_FF(a, b, c, d, in[0], _md5_S11, 0xD76AA478);
|
||||
_md5_FF(d, a, b, c, in[1], _md5_S12, 0xE8C7B756);
|
||||
_md5_FF(c, d, a, b, in[2], _md5_S13, 0x242070DB);
|
||||
_md5_FF(b, c, d, a, in[3], _md5_S14, 0xC1BDCEEE);
|
||||
_md5_FF(a, b, c, d, in[4], _md5_S11, 0xF57C0FAF);
|
||||
_md5_FF(d, a, b, c, in[5], _md5_S12, 0x4787C62A);
|
||||
_md5_FF(c, d, a, b, in[6], _md5_S13, 0xA8304613);
|
||||
_md5_FF(b, c, d, a, in[7], _md5_S14, 0xFD469501);
|
||||
_md5_FF(a, b, c, d, in[8], _md5_S11, 0x698098D8);
|
||||
_md5_FF(d, a, b, c, in[9], _md5_S12, 0x8B44F7AF);
|
||||
_md5_FF(c, d, a, b, in[10], _md5_S13, 0xFFFF5BB1);
|
||||
_md5_FF(b, c, d, a, in[11], _md5_S14, 0x895CD7BE);
|
||||
_md5_FF(a, b, c, d, in[12], _md5_S11, 0x6B901122);
|
||||
_md5_FF(d, a, b, c, in[13], _md5_S12, 0xFD987193);
|
||||
_md5_FF(c, d, a, b, in[14], _md5_S13, 0xA679438E);
|
||||
_md5_FF(b, c, d, a, in[15], _md5_S14, 0x49B40821);
|
||||
|
||||
//
|
||||
_md5_GG(a, b, c, d, in[1], _md5_S21, 0xF61E2562);
|
||||
_md5_GG(d, a, b, c, in[6], _md5_S22, 0xC040B340);
|
||||
_md5_GG(c, d, a, b, in[11], _md5_S23, 0x265E5A51);
|
||||
_md5_GG(b, c, d, a, in[0], _md5_S24, 0xE9B6C7AA);
|
||||
_md5_GG(a, b, c, d, in[5], _md5_S21, 0xD62F105D);
|
||||
_md5_GG(d, a, b, c, in[10], _md5_S22, 0x02441453);
|
||||
_md5_GG(c, d, a, b, in[15], _md5_S23, 0xD8A1E681);
|
||||
_md5_GG(b, c, d, a, in[4], _md5_S24, 0xE7D3FBC8);
|
||||
_md5_GG(a, b, c, d, in[9], _md5_S21, 0x21E1CDE6);
|
||||
_md5_GG(d, a, b, c, in[14], _md5_S22, 0xC33707D6);
|
||||
_md5_GG(c, d, a, b, in[3], _md5_S23, 0xF4D50D87);
|
||||
_md5_GG(b, c, d, a, in[8], _md5_S24, 0x455A14ED);
|
||||
_md5_GG(a, b, c, d, in[13], _md5_S21, 0xA9E3E905);
|
||||
_md5_GG(d, a, b, c, in[2], _md5_S22, 0xFCEFA3F8);
|
||||
_md5_GG(c, d, a, b, in[7], _md5_S23, 0x676F02D9);
|
||||
_md5_GG(b, c, d, a, in[12], _md5_S24, 0x8D2A4C8A);
|
||||
|
||||
//
|
||||
_md5_HH(a, b, c, d, in[5], _md5_S31, 0xFFFA3942);
|
||||
_md5_HH(d, a, b, c, in[8], _md5_S32, 0x8771F681);
|
||||
_md5_HH(c, d, a, b, in[11], _md5_S33, 0x6D9D6122);
|
||||
_md5_HH(b, c, d, a, in[14], _md5_S34, 0xFDE5380C);
|
||||
_md5_HH(a, b, c, d, in[1], _md5_S31, 0xA4BEEA44);
|
||||
_md5_HH(d, a, b, c, in[4], _md5_S32, 0x4BDECFA9);
|
||||
_md5_HH(c, d, a, b, in[7], _md5_S33, 0xF6BB4B60);
|
||||
_md5_HH(b, c, d, a, in[10], _md5_S34, 0xBEBFBC70);
|
||||
_md5_HH(a, b, c, d, in[13], _md5_S31, 0x289B7EC6);
|
||||
_md5_HH(d, a, b, c, in[0], _md5_S32, 0xEAA127FA);
|
||||
_md5_HH(c, d, a, b, in[3], _md5_S33, 0xD4EF3085);
|
||||
_md5_HH(b, c, d, a, in[6], _md5_S34, 0x04881D05);
|
||||
_md5_HH(a, b, c, d, in[9], _md5_S31, 0xD9D4D039);
|
||||
_md5_HH(d, a, b, c, in[12], _md5_S32, 0xE6DB99E5);
|
||||
_md5_HH(c, d, a, b, in[15], _md5_S33, 0x1FA27CF8);
|
||||
_md5_HH(b, c, d, a, in[2], _md5_S34, 0xC4AC5665);
|
||||
|
||||
//
|
||||
_md5_II(a, b, c, d, in[0], _md5_S41, 0xF4292244);
|
||||
_md5_II(d, a, b, c, in[7], _md5_S42, 0x432AFF97);
|
||||
_md5_II(c, d, a, b, in[14], _md5_S43, 0xAB9423A7);
|
||||
_md5_II(b, c, d, a, in[5], _md5_S44, 0xFC93A039);
|
||||
_md5_II(a, b, c, d, in[12], _md5_S41, 0x655B59C3);
|
||||
_md5_II(d, a, b, c, in[3], _md5_S42, 0x8F0CCC92);
|
||||
_md5_II(c, d, a, b, in[10], _md5_S43, 0xFFEFF47D);
|
||||
_md5_II(b, c, d, a, in[1], _md5_S44, 0x85845DD1);
|
||||
_md5_II(a, b, c, d, in[8], _md5_S41, 0x6FA87E4F);
|
||||
_md5_II(d, a, b, c, in[15], _md5_S42, 0xFE2CE6E0);
|
||||
_md5_II(c, d, a, b, in[6], _md5_S43, 0xA3014314);
|
||||
_md5_II(b, c, d, a, in[13], _md5_S44, 0x4E0811A1);
|
||||
_md5_II(a, b, c, d, in[4], _md5_S41, 0xF7537E82);
|
||||
_md5_II(d, a, b, c, in[11], _md5_S42, 0xBD3AF235);
|
||||
_md5_II(c, d, a, b, in[2], _md5_S43, 0x2AD7D2BB);
|
||||
_md5_II(b, c, d, a, in[9], _md5_S44, 0xEB86D391);
|
||||
|
||||
//
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,319 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class Library
|
||||
// ----------------------------------------------
|
||||
// Name: XSCEABaseProvider
|
||||
// Description: provides base requirements for
|
||||
// Specific Sgnal Provider ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// START Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// Includes ...
|
||||
#include "../Libraries/x-saherelm.log.lib.mq5"
|
||||
#include "../Libraries/x-saherelm.draw.lib.mq5"
|
||||
#include "../Libraries/x-saherelm.models.lib.mq5"
|
||||
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||
|
||||
//
|
||||
// END Import and Inclused requirements ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Notified a Signal was Appears ...
|
||||
typedef void (*OnSignal)(
|
||||
XSignal &signal);
|
||||
|
||||
//
|
||||
// Notified a Guard Appears ...
|
||||
typedef void (*OnGuard)(XGuard &guard);
|
||||
|
||||
//
|
||||
// END Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// END Overrides ...
|
||||
//
|
||||
|
||||
//
|
||||
// a Base Class for All of our EA's ...
|
||||
class XSCEABaseProvider
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Constructor ...
|
||||
void XSCEABaseProvider()
|
||||
{
|
||||
mSymbol = _Symbol;
|
||||
mPeriod = _Period;
|
||||
}
|
||||
void XSCEABaseProvider(
|
||||
string symbol,
|
||||
ENUM_TIMEFRAMES period,
|
||||
bool ignoreTicksAfterSignalTillNewCandle = true)
|
||||
{
|
||||
//
|
||||
mSymbol = symbol;
|
||||
mPeriod = period;
|
||||
|
||||
//
|
||||
mTag = mSymbol + "," + ToString(mPeriod);
|
||||
|
||||
//
|
||||
mIsInTestMode = IsRunningOnTestMode();
|
||||
|
||||
//
|
||||
mIgnoreTicksAfterSignalTillNewCandle = ignoreTicksAfterSignalTillNewCandle;
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
void ~XSCEABaseProvider()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
bool CanIgnoreTick()
|
||||
{
|
||||
//
|
||||
mIsNewCandle = IsNewCandle(
|
||||
mSymbol,
|
||||
mPeriod);
|
||||
bool result = mIsInTestMode
|
||||
? !mIsNewCandle
|
||||
: !mIsNewCandle && mWaitUntilNewCandle;
|
||||
|
||||
//
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
result = mIgnoreTicksAfterSignalTillNewCandle;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare State ...
|
||||
void OnTick()
|
||||
{
|
||||
//
|
||||
mIsNewCandle = IsNewCandle(
|
||||
mSymbol,
|
||||
mPeriod);
|
||||
mCanIgnoreTick = mIsInTestMode
|
||||
? !mIsNewCandle
|
||||
: !mIsNewCandle && mWaitUntilNewCandle;
|
||||
|
||||
//
|
||||
ProcessBuffers();
|
||||
|
||||
//
|
||||
if (mCanIgnoreTick)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
mWaitUntilNewCandle = false;
|
||||
|
||||
//
|
||||
ProcessTick();
|
||||
}
|
||||
|
||||
//
|
||||
virtual void PrepareTag();
|
||||
|
||||
//
|
||||
// Initialize Indicators and Requirements ...
|
||||
virtual bool Init();
|
||||
|
||||
//
|
||||
virtual int GetMaxLength();
|
||||
|
||||
//
|
||||
virtual int GetCalculatedBars();
|
||||
|
||||
//
|
||||
// Handle Update Buffers ...
|
||||
virtual void ProcessBuffers()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle On Tick Event ...
|
||||
virtual void ProcessTick()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for Guards ...
|
||||
virtual bool GuardCheck(XGuard &guards[]);
|
||||
|
||||
//
|
||||
// Add Specific On Signal Event Handler ...
|
||||
int AddOnSignalEventHandler(OnSignal handler)
|
||||
{
|
||||
//
|
||||
ArrayResize(
|
||||
mSignalEventHandlers,
|
||||
ArraySize(mSignalEventHandlers) + 1);
|
||||
|
||||
//
|
||||
int result = ArraySize(mSignalEventHandlers) - 1;
|
||||
mSignalEventHandlers[result] = handler;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove All On Signal Event Handler ...
|
||||
void ReoveOnSignalEventHandlers()
|
||||
{
|
||||
//
|
||||
ArrayFree(mSignalEventHandlers);
|
||||
}
|
||||
|
||||
//
|
||||
// Notify a Signal Found on all Event Listeners ...
|
||||
void NotifyOnSignalEvent(XSignal &info)
|
||||
{
|
||||
//
|
||||
int listenerCount = ArraySize(mSignalEventHandlers);
|
||||
if (listenerCount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop Through Listeners ...
|
||||
for (int i = 0; i < listenerCount; i++)
|
||||
{
|
||||
//
|
||||
OnSignal listener = mSignalEventHandlers[i];
|
||||
|
||||
//
|
||||
listener(info);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
string mSymbol;
|
||||
|
||||
//
|
||||
ENUM_TIMEFRAMES mPeriod;
|
||||
|
||||
//
|
||||
string mTag;
|
||||
|
||||
//
|
||||
bool mIsNewCandle;
|
||||
bool mIsInTestMode;
|
||||
bool mCanIgnoreTick;
|
||||
bool mWaitUntilNewCandle;
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Signal Event Handlers ...
|
||||
OnSignal mSignalEventHandlers[];
|
||||
|
||||
//
|
||||
bool mIgnoreTicksAfterSignalTillNewCandle;
|
||||
};
|
||||
|
||||
//
|
||||
// START Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Model Signal Providers Definitions ...
|
||||
struct XBaseSignalProvider
|
||||
{
|
||||
//
|
||||
// Provider use Which Symbol ...
|
||||
string symbol;
|
||||
|
||||
//
|
||||
// Provider use Which Time Frame ...
|
||||
ENUM_TIMEFRAMES period;
|
||||
|
||||
//
|
||||
// Risk Amount Per Trades Related to Time Frames ...
|
||||
// Percent of Available Balance ...
|
||||
double riskAmount;
|
||||
|
||||
//
|
||||
// Desired Magic Number ...
|
||||
ulong magicNumber;
|
||||
};
|
||||
|
||||
//
|
||||
struct XLastSignal
|
||||
{
|
||||
datetime at;
|
||||
string provider;
|
||||
};
|
||||
|
||||
//
|
||||
// END Definitions ...
|
||||
//
|
||||
|
||||
//
|
||||
// START Usefull Functions ...
|
||||
//
|
||||
|
||||
//
|
||||
// Add Specific Provider to List ...
|
||||
void Add(
|
||||
XBaseSignalProvider &item, // item want to add
|
||||
XBaseSignalProvider &buffer[] // Destination buffer
|
||||
)
|
||||
{
|
||||
//
|
||||
ArrayResize(
|
||||
buffer,
|
||||
ArraySize(buffer) + 1);
|
||||
|
||||
//
|
||||
buffer[ArraySize(buffer) - 1] = item;
|
||||
}
|
||||
|
||||
//
|
||||
// END Usefull Functions ...
|
||||
//
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,506 @@
|
||||
/**
|
||||
* XColor Tools Module ...
|
||||
* a module for handle colorify text contents in node js ...
|
||||
*
|
||||
* Maintainer
|
||||
*
|
||||
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
|
||||
*/
|
||||
|
||||
//
|
||||
//#region Module Imports ...
|
||||
const XValueTools = require("./x-value.tools");
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
/**
|
||||
* these are available style which can applied to an string ...
|
||||
*/
|
||||
const AVAILABLE_STYLES = {
|
||||
//
|
||||
Bold: "\x1b[1m",
|
||||
Dim: "\x1b[2m",
|
||||
Underlined: "\x1b[4m",
|
||||
Blink: "\x1b[5m",
|
||||
ReverseFandB: "\x1b[7m",
|
||||
Hidden: "\x1b[8m",
|
||||
//
|
||||
// Commonly used for reset all Styles ...
|
||||
Reset: "\x1b[0m"
|
||||
};
|
||||
|
||||
/**
|
||||
* these are available foreground colors which can applied to an string ...
|
||||
*/
|
||||
const AVAILABLE_FOREGROUND_COLORS = {
|
||||
Default: "\x1b[39m",
|
||||
Black: "\x1b[30m",
|
||||
Red: "\x1b[31m",
|
||||
Green: "\x1b[32m",
|
||||
Yellow: "\x1b[33m",
|
||||
Blue: "\x1b[34m",
|
||||
Magenta: "\x1b[35m",
|
||||
Cyan: "\x1b[36m",
|
||||
LightGray: "\x1b[37m",
|
||||
DarkGray: "\x1b[90m",
|
||||
LightRed: "\x1b[91m",
|
||||
LightGreen: "\x1b[92m",
|
||||
LightYellow: "\x1b[93m",
|
||||
LightBlue: "\x1b[94m",
|
||||
LightMagenta: "\x1b[95m",
|
||||
LightCyan: "\x1b[96m",
|
||||
White: "\x1b[97m",
|
||||
};
|
||||
|
||||
/**
|
||||
* these are available background colors which can applied to an string ...
|
||||
*/
|
||||
const AVAILABLE_BACKGROUND_COLORS = {
|
||||
Default: "\x1b[49m",
|
||||
Black: "\x1b[40m",
|
||||
Red: "\x1b[41m",
|
||||
Green: "\x1b[42m",
|
||||
Yellow: "\x1b[43m",
|
||||
Blue: "\x1b[44m",
|
||||
Magenta: "\x1b[45m",
|
||||
Cyan: "\x1b[46m",
|
||||
LightGray: "\x1b[47m",
|
||||
DarkGray: "\x1b[100m",
|
||||
LightRed: "\x1b[101m",
|
||||
LightGreen: "\x1b[102m",
|
||||
LightYellow: "\x1b[103m",
|
||||
LightBlue: "\x1b[104m",
|
||||
LightMagenta: "\x1b[105m",
|
||||
LightCyan: "\x1b[106m",
|
||||
White: "\x1b[107m",
|
||||
};
|
||||
|
||||
/**
|
||||
* these are available style names, which exports from module and
|
||||
* users can use them ...
|
||||
*/
|
||||
const STYLE_NAMES = {
|
||||
Bold: "Bold",
|
||||
Dim: "Dim",
|
||||
Underlined: "Underlined",
|
||||
Blink: "Blink",
|
||||
ReverseFandB: "ReverseFandB",
|
||||
Hidden: "Hidden",
|
||||
Reset: "Reset",
|
||||
};
|
||||
|
||||
/**
|
||||
* these are available color names, which exports from module and
|
||||
* users can use them ...
|
||||
*/
|
||||
const COLOR_NAMES = {
|
||||
Default: "Default",
|
||||
Black: "Black",
|
||||
Red: "Red",
|
||||
Green: "Green",
|
||||
Yellow: "Yellow",
|
||||
Blue: "Blue",
|
||||
Magenta: "Magenta",
|
||||
Cyan: "Cyan",
|
||||
LightGray: "LightGray",
|
||||
DarkGray: "DarkGray",
|
||||
LightRed: "LightRed",
|
||||
LightGreen: "LightGreen",
|
||||
LightYellow: "LightYellow",
|
||||
LightBlue: "LightBlue",
|
||||
LightMagenta: "LightMagenta",
|
||||
LightCyan: "LightCyan",
|
||||
White: "White",
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
/**
|
||||
* apply specified style and color on a content ...
|
||||
*
|
||||
* @param {string} content specified content for styling ...
|
||||
* @param {string} color specific color name for using to styling ...
|
||||
* @param {string} style soecufic style name to use ...
|
||||
* @param {boolean} toForeground apply specified color as foreground ...
|
||||
* @param {boolean} toBackground apply specified color as background ...
|
||||
* @returns {string} styled content ...
|
||||
*/
|
||||
function apply(
|
||||
content,
|
||||
color,
|
||||
style,
|
||||
toForeground = true,
|
||||
toBackground = false
|
||||
) {
|
||||
//
|
||||
let result = content;
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Style and Apply it ...
|
||||
let eStyle = AVAILABLE_STYLES[style];
|
||||
if (XValueTools.isValidArg(eStyle)) {
|
||||
result = `${eStyle}${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Foreground Color and Apply it ...
|
||||
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
|
||||
if (
|
||||
!!toForeground
|
||||
&& XValueTools.isValidArg(eFColor)
|
||||
) {
|
||||
result = `${eFColor}${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Background Color and Apply it ...
|
||||
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
|
||||
if (
|
||||
!!toBackground
|
||||
&& XValueTools.isValidArg(eBColor)
|
||||
) {
|
||||
result = `${eBColor}${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* apply specific style on a content ...
|
||||
*
|
||||
* @param {string} content specific content which going to styled ...
|
||||
* @param {string} style a member of STYLE_NAMES which specified that which style going to applied to content ...
|
||||
* @returns {string} styled content ...
|
||||
*/
|
||||
function applyStyle(content, style) {
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
let eStyle = AVAILABLE_STYLES[style];
|
||||
if (eStyle === undefined) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
return `${eStyle}${content}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* apply specific foreground color on a content ...
|
||||
*
|
||||
* @param {string} content specific content which going to colorified ...
|
||||
* @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ...
|
||||
* @returns {string} colorified content ...
|
||||
*/
|
||||
function applyForegroundColor(content, color) {
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
let eColor = AVAILABLE_FOREGROUND_COLORS[color];
|
||||
if (eColor === undefined) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
return `${eColor}${content}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* apply specific background color on a content ...
|
||||
*
|
||||
* @param {string} content specific content which going to colorified ...
|
||||
* @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ...
|
||||
* @returns {string} colorified content ...
|
||||
*/
|
||||
function applyBackgroundColor(content, color) {
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
let eColor = AVAILABLE_BACKGROUND_COLORS[color];
|
||||
if (eColor === undefined) {
|
||||
return content;
|
||||
}
|
||||
|
||||
//
|
||||
return `${eColor}${content}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate style and color applier expression ...
|
||||
*
|
||||
* @param {string} color specific color name for using to styling ...
|
||||
* @param {string} style soecufic style name to use ...
|
||||
* @param {boolean} reset close applier string by reset styles ...
|
||||
* @param {boolean} toForeground apply specified color as foreground ...
|
||||
* @param {boolean} toBackground apply specified color as background ...
|
||||
* @returns {string} style and color applier string ...
|
||||
*/
|
||||
function getApplier(
|
||||
style = "",
|
||||
color = "",
|
||||
reset = false,
|
||||
toForeground = true,
|
||||
toBackground = false
|
||||
) {
|
||||
//
|
||||
let result = "";
|
||||
|
||||
//
|
||||
// Detect and Validate Style and Apply it ...
|
||||
let eStyle = AVAILABLE_STYLES[style];
|
||||
if (XValueTools.isValidArg(eStyle)) {
|
||||
result = `${eStyle}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Foreground Color and Apply it ...
|
||||
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
|
||||
if (
|
||||
!!toForeground
|
||||
&& XValueTools.isValidArg(eFColor)
|
||||
) {
|
||||
result = `${eFColor}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Background Color and Apply it ...
|
||||
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
|
||||
if (
|
||||
!!toBackground
|
||||
&& XValueTools.isValidArg(eBColor)
|
||||
) {
|
||||
result = `${eBColor}`;
|
||||
}
|
||||
|
||||
//
|
||||
if (
|
||||
!!reset &&
|
||||
result.length > 0
|
||||
) {
|
||||
result = `${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate style applier expression ...
|
||||
*
|
||||
* @param {string} style soecufic style name to use ...
|
||||
* @param {boolean} reset close applier string by reset styles ...
|
||||
* @returns {string} style applier string ...
|
||||
*/
|
||||
function getStyleApplier(
|
||||
style = "",
|
||||
reset = false
|
||||
) {
|
||||
//
|
||||
let result = "";
|
||||
|
||||
//
|
||||
// Detect and Validate Style and Apply it ...
|
||||
let eStyle = AVAILABLE_STYLES[style];
|
||||
if (XValueTools.isValidArg(eStyle)) {
|
||||
result = `${eStyle}`;
|
||||
}
|
||||
|
||||
//
|
||||
if (
|
||||
!!reset &&
|
||||
result.length > 0
|
||||
) {
|
||||
result = `${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate color applier expression ...
|
||||
*
|
||||
* @param {string} color specific color name for using to styling ...
|
||||
* @param {boolean} reset close applier string by reset styles ...
|
||||
* @param {boolean} toForeground apply specified color as foreground ...
|
||||
* @param {boolean} toBackground apply specified color as background ...
|
||||
* @returns {string} color applier string ...
|
||||
*/
|
||||
function getColorApplier(
|
||||
color = "",
|
||||
reset = false,
|
||||
toForeground = true,
|
||||
toBackground = false
|
||||
) {
|
||||
//
|
||||
let result = "";
|
||||
|
||||
//
|
||||
// Detect and Validate Foreground Color and Apply it ...
|
||||
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
|
||||
if (
|
||||
!!toForeground
|
||||
&& XValueTools.isValidArg(eFColor)
|
||||
) {
|
||||
result = `${eFColor}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Background Color and Apply it ...
|
||||
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
|
||||
if (
|
||||
!!toBackground
|
||||
&& XValueTools.isValidArg(eBColor)
|
||||
) {
|
||||
result = `${eBColor}`;
|
||||
}
|
||||
|
||||
//
|
||||
if (
|
||||
!!reset &&
|
||||
result.length > 0
|
||||
) {
|
||||
result = `${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* colorified specific content ...
|
||||
*
|
||||
* @param {string} content specified content for styling ...
|
||||
* @param {string} color specific color name for using to styling ...
|
||||
* @param {boolean} toForeground apply specified color as foreground ...
|
||||
* @param {boolean} toBackground apply specified color as background ...
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorifyContent(
|
||||
content = "",
|
||||
color = "",
|
||||
toForeground = true,
|
||||
toBackground = false
|
||||
) {
|
||||
//
|
||||
let result = content;
|
||||
|
||||
//
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Finde Colors ...
|
||||
|
||||
//
|
||||
// Detect and Validate Foreground Color and Apply it ...
|
||||
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
|
||||
if (
|
||||
!!toForeground
|
||||
&& XValueTools.isValidArg(eFColor)
|
||||
) {
|
||||
result = `${eFColor}${result}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Background Color and Apply it ...
|
||||
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
|
||||
if (
|
||||
!!toBackground
|
||||
&& XValueTools.isValidArg(eBColor)
|
||||
) {
|
||||
result = `${eBColor}${result}`;
|
||||
}
|
||||
|
||||
//
|
||||
if (
|
||||
result.length > 0
|
||||
&& (
|
||||
XValueTools.isValidArg(eFColor) ||
|
||||
XValueTools.isValidArg(eBColor)
|
||||
)
|
||||
) {
|
||||
result = `${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* apply style on specific content ...
|
||||
*
|
||||
* @param {string} content specified content for styling ...
|
||||
* @param {string} style soecufic style name to use ...
|
||||
* @returns {string}
|
||||
*/
|
||||
function stylifiyContent(
|
||||
content = "",
|
||||
style = "",
|
||||
) {
|
||||
//
|
||||
let result = content;
|
||||
|
||||
//
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect and Validate Style and Apply it ...
|
||||
let eStyle = AVAILABLE_STYLES[style];
|
||||
if (XValueTools.isValidArg(eStyle)) {
|
||||
result = `${eStyle}${result}`;
|
||||
}
|
||||
|
||||
//
|
||||
if (
|
||||
result.length > 0
|
||||
&& XValueTools.isValidArg(eStyle)
|
||||
) {
|
||||
result = `${result}${AVAILABLE_STYLES.Reset}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
STYLE_NAMES,
|
||||
COLOR_NAMES,
|
||||
//
|
||||
apply,
|
||||
applyStyle,
|
||||
getApplier,
|
||||
getColorApplier,
|
||||
getStyleApplier,
|
||||
colorifyContent,
|
||||
stylifiyContent,
|
||||
applyForegroundColor,
|
||||
applyBackgroundColor,
|
||||
}
|
||||
//#endregion
|
||||
@@ -0,0 +1,830 @@
|
||||
/**
|
||||
* XFile Tools Module ...
|
||||
* a module for handle all file/folder manipulating task in node js ...
|
||||
*
|
||||
* Maintainer
|
||||
*
|
||||
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
|
||||
*/
|
||||
|
||||
//
|
||||
//#region Module Imports ...
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const Path = require('path');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const XValueTools = require('./x-value.tools');
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
/**
|
||||
* current os path separators ...
|
||||
*/
|
||||
const PathSeparator = Path.sep;
|
||||
|
||||
/**
|
||||
* current directory ...
|
||||
*/
|
||||
const CurrentDir = __dirname;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//
|
||||
//#region Global ...
|
||||
/**
|
||||
* retrieve a path status ...
|
||||
*
|
||||
* @param {string} path a path value to check ...
|
||||
* @returns an stat object ...
|
||||
*/
|
||||
function getStatus(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
return fs.statSync(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve user's Home path ...
|
||||
*
|
||||
* @returns {string} a path ...
|
||||
*/
|
||||
function getHomePath() {
|
||||
return os.homedir();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Path ...
|
||||
/**
|
||||
* retrieve the base name of specific address path ...
|
||||
*
|
||||
* @param {string} path address of file or folder ...
|
||||
* @returns string ...
|
||||
*/
|
||||
function basename(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
const result = Path.basename(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* join several path segments together ...
|
||||
*
|
||||
* @param {...string} path path params ...
|
||||
* @returns a joined paths ...
|
||||
*/
|
||||
function joinPath(...path) {
|
||||
return Path.join(...path);
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve a relative path to absolute ...
|
||||
*
|
||||
* @param {string[]} path a path value to check ...
|
||||
* @returns {string}
|
||||
*/
|
||||
function resolvePath(...path) {
|
||||
return Path.resolve(...path);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region File ...
|
||||
/**
|
||||
* determines a path destination is a file or not ...
|
||||
*
|
||||
* @param {string} path a path value to check ...
|
||||
* @returns a boolean value ...
|
||||
*/
|
||||
function isFileExists(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
const stat = getStatus(path);
|
||||
if (!stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
return stat.isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a file ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function removeFile(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isFileExists(path)) {
|
||||
resolve(false);
|
||||
}
|
||||
|
||||
//
|
||||
fs.unlink(path, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* copy a file to destination path ...
|
||||
*
|
||||
* @param {string} source source file path ...
|
||||
* @param {string} dest dest folder path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function copyFile(
|
||||
source = '',
|
||||
dest = ''
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (
|
||||
!isFileExists(source) ||
|
||||
!isDirectoryExists(dest)
|
||||
) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const destFilePath = Path.join(dest, Path.basename(source));
|
||||
fs.copyFile(source, destFilePath, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* reading specified file content ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @returns {Promise<string>} file content ...
|
||||
*/
|
||||
function readFile(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isFileExists(path)) {
|
||||
resolve('');
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readFile(path, 'utf8', (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* write content to a file ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @param {string} content the content which going to write to the file ...
|
||||
* @param {bool} overwrite determines file overwrite if exists ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function writeFile(
|
||||
path = '',
|
||||
content = '',
|
||||
overwrite = true
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (isFileExists(path) && !overwrite) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Content ...
|
||||
content = XValueTools.isValidArg(content) ?
|
||||
content :
|
||||
'';
|
||||
|
||||
//
|
||||
fs.writeFile(path, content, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* create a file ...
|
||||
*
|
||||
* @param {string} path file path ...
|
||||
* @param {string} fileName file name ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function createFile(
|
||||
path = '',
|
||||
fileName = ''
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
const filePath = Path.join(path, fileName);
|
||||
if (
|
||||
isFileExists(filePath) ||
|
||||
!XValueTools.isValidArg(path) ||
|
||||
!XValueTools.isValidArg(fileName)
|
||||
) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.writeFile(filePath, '', (err) => {
|
||||
//
|
||||
if (err) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a file name extension ...
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {string} name without extension ...
|
||||
*/
|
||||
function removeFileExtension(name = '') {
|
||||
return name.substring(0, name.lastIndexOf('.')) || name;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a file extension ...
|
||||
*
|
||||
* @param {string} path a path which locate a file ...
|
||||
* @returns {string}
|
||||
*/
|
||||
function getFileExtension(path = '') {
|
||||
//
|
||||
let result = "";
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (
|
||||
!XValueTools.isValidArg(path)
|
||||
|| !isFileExists(path)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve just file name ...
|
||||
const fileName = basename(path);
|
||||
result = fileName.replace(
|
||||
removeFileExtension(fileName),
|
||||
""
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve all files list recursively from specific path ...
|
||||
*
|
||||
* @param {string} path a source folder path ...
|
||||
* @param {string[]} extensions which file extensions need to be listed, live empty for all files ...
|
||||
* @returns {Promise<string[]>}
|
||||
*/
|
||||
async function getRecursiveFilesList(
|
||||
path = "",
|
||||
extensions = []
|
||||
) {
|
||||
//
|
||||
let result = [];
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(path)
|
||||
|| !isDirectoryExists(path)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
const contents = await getDirectoryContents(path);
|
||||
for(const item of contents) {
|
||||
//
|
||||
const itemPath = joinPath(
|
||||
path,
|
||||
item
|
||||
);
|
||||
|
||||
//
|
||||
const isItemFile = isFileExists(itemPath);
|
||||
if (isItemFile) {
|
||||
//
|
||||
const itemFileExtension = getFileExtension(itemPath);
|
||||
const isFileInSupportedExtensions =
|
||||
extensions === undefined || extensions.length === 0
|
||||
? true
|
||||
: extensions.includes(itemFileExtension)
|
||||
;
|
||||
if (isFileInSupportedExtensions) {
|
||||
result.push(itemPath);
|
||||
}
|
||||
} else if (isDirectoryExists(itemPath)) {
|
||||
//
|
||||
const itemPathFiles = await getRecursiveFilesList(itemPath, extensions);
|
||||
result.push(...itemPathFiles);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Directory ...
|
||||
/**
|
||||
* create a directory ...
|
||||
*
|
||||
* @param {string} path destination path including dir name ...
|
||||
* @param {boolean} recursive create directories recursively ...
|
||||
* @returns action done or not ...
|
||||
*/
|
||||
function createDirectory(
|
||||
path = '',
|
||||
recursive = true
|
||||
) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
if (
|
||||
isDirectoryExists(path) ||
|
||||
!XValueTools.isValidArg(path)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
fs.mkdirSync(path, { recursive: recursive });
|
||||
result = true;
|
||||
return result;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a directory ...
|
||||
*
|
||||
* @param {string} path destination path including dir name ...
|
||||
* @param {boolean} recursive removes directories recursively ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function removeDirectory(
|
||||
path = '',
|
||||
recursive = false
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.rm(path, {
|
||||
recursive
|
||||
}, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* determines a path destination is a directory or not ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns represent destnation path is Directory or not ...
|
||||
*/
|
||||
function isDirectoryExists(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
const isExists = fs.existsSync(path);
|
||||
if (!isExists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const stat = getStatus(path);
|
||||
if (!stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const result = stat.isDirectory();
|
||||
return result;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory content ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder files ...
|
||||
*/
|
||||
function getDirectoryContents(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory files ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder files ...
|
||||
*/
|
||||
function getDirectoryFiles(
|
||||
path = '',
|
||||
containsHiddenFiles = false
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (!containsHiddenFiles) {
|
||||
content = content.filter(c => !c.startsWith('.'));
|
||||
}
|
||||
|
||||
//
|
||||
const result = [];
|
||||
content
|
||||
.forEach(c => {
|
||||
//
|
||||
const cPath = Path.join(path, c);
|
||||
if (isFileExists(cPath)) {
|
||||
result.push(c);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory folders ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder names ...
|
||||
*/
|
||||
function getDirectoryFolders(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const result = [];
|
||||
content.forEach(c => {
|
||||
//
|
||||
const cPath = Path.join(path, c);
|
||||
if (isDirectoryExists(cPath)) {
|
||||
result.push(c);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* copy a folder with all of it's content to dest ...
|
||||
*
|
||||
* @param {string} source source folder path ...
|
||||
* @param {string} dest dest folder path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
async function copyFolder(
|
||||
source = '',
|
||||
dest = ''
|
||||
) {
|
||||
//
|
||||
if (
|
||||
!isDirectoryExists(source) ||
|
||||
!XValueTools.isValidArg(dest) ||
|
||||
!XValueTools.isValidArg(source)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const folderName = Path.basename(source);
|
||||
const destPath = Path.join(dest, folderName);
|
||||
|
||||
//
|
||||
// Create Dest Path folder if not exists ...
|
||||
if (!isDirectoryExists(destPath)) {
|
||||
//
|
||||
let result = createDirectory(destPath, true);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Files ...
|
||||
const files = await getDirectoryFiles(source);
|
||||
if (files && files.constructor === Array && files.length > 0) {
|
||||
//
|
||||
const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath));
|
||||
const filesResult = (await Promise.all(filesPromises)).every(r => !!r);
|
||||
if (!filesResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Folders ...
|
||||
const folders = await getDirectoryFolders(source);
|
||||
if (folders && folders.constructor === Array && folders.length > 0) {
|
||||
//
|
||||
const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath));
|
||||
const filesResult = (await Promise.all(folderPromises)).every(r => !!r);
|
||||
if (!filesResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Downloader ...
|
||||
/**
|
||||
* download a file from specific url and store it ...
|
||||
*
|
||||
* @param {string} filepath the file name and path which required to put download file on it ...
|
||||
* @param {string} url the web url for downloading ...
|
||||
*/
|
||||
function download(filepath, url) {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(url)
|
||||
|| !XValueTools.isValidURL(url)
|
||||
|| !XValueTools.isValidArg(filepath)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
var file = fs.createWriteStream(filepath);
|
||||
|
||||
//
|
||||
if (url.startsWith('https:')) {
|
||||
https.get(url, function (response) {
|
||||
response.pipe(file);
|
||||
});
|
||||
} else if (url.startsWith('http:')) {
|
||||
http.get(url, function (response) {
|
||||
response.pipe(file);
|
||||
});
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region JSON ...
|
||||
/**
|
||||
* read and parse a JSON content from a file ...
|
||||
*
|
||||
* @param {string} path source file path ...
|
||||
* @returns {any}
|
||||
*/
|
||||
function readJSON(path = "") {
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!isFileExists(path)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
let result = undefined;
|
||||
try {
|
||||
result = require(path);
|
||||
} catch {
|
||||
result = undefined;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* write a JSON Object content into a file ...
|
||||
*
|
||||
* @param {string} path dest file path ...
|
||||
* @param {any} content an object which required to write to file ...
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function writeJSON(
|
||||
path = "",
|
||||
content = undefined
|
||||
) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Normallize Content ...
|
||||
if (content === undefined) {
|
||||
content = {};
|
||||
}
|
||||
|
||||
//
|
||||
const contentString = XValueTools.beautifyJSON(content);
|
||||
|
||||
//
|
||||
result = await writeFile(
|
||||
path,
|
||||
contentString,
|
||||
true
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
CurrentDir,
|
||||
PathSeparator,
|
||||
|
||||
//
|
||||
getStatus,
|
||||
getHomePath,
|
||||
|
||||
//
|
||||
basename,
|
||||
joinPath,
|
||||
resolvePath,
|
||||
|
||||
//
|
||||
download,
|
||||
|
||||
//
|
||||
readJSON,
|
||||
writeJSON,
|
||||
|
||||
//
|
||||
copyFile,
|
||||
readFile,
|
||||
writeFile,
|
||||
createFile,
|
||||
removeFile,
|
||||
isFileExists,
|
||||
getFileExtension,
|
||||
removeFileExtension,
|
||||
getRecursiveFilesList,
|
||||
|
||||
//
|
||||
copyFolder,
|
||||
createDirectory,
|
||||
removeDirectory,
|
||||
createDirectory,
|
||||
removeDirectory,
|
||||
isDirectoryExists,
|
||||
isDirectoryExists,
|
||||
getDirectoryFiles,
|
||||
getDirectoryFolders,
|
||||
getDirectoryContents,
|
||||
}
|
||||
//#endregion
|
||||
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* XShell Tools Module ...
|
||||
* a module for handling shell actions and retrieve OS Info in node js ...
|
||||
*
|
||||
* Maintainer
|
||||
*
|
||||
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
|
||||
*/
|
||||
|
||||
//
|
||||
//#region Imports ...
|
||||
const os = require('os');
|
||||
const process = require('process');
|
||||
const { exec } = require("child_process");
|
||||
const XFileTools = require('./x-file.tools');
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
//
|
||||
const OS = {
|
||||
Aix: 'aix',
|
||||
Darwin: 'darwin',
|
||||
FreeBSD: 'freebsd',
|
||||
Linux: 'linux',
|
||||
OpenBSD: 'openbsd',
|
||||
SnOS: 'sunos',
|
||||
Windows: 'win32'
|
||||
};
|
||||
|
||||
//
|
||||
const isWindows = process.platform === OS.Windows;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//
|
||||
//#region Pure shell commands ...
|
||||
/**
|
||||
* execute a command using NodeJS on shell ...
|
||||
*
|
||||
* @param {string} cmd command to execute ...
|
||||
* @param {string} cwd working directory ...
|
||||
*
|
||||
* @returns Promise<any, errr> instance ...
|
||||
*/
|
||||
function execute(cmd, cwd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
//
|
||||
if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) {
|
||||
reject('invalid args ...');
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
exec(cmd, { cwd }, (err, result, stdError) => {
|
||||
//
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (stdError) {
|
||||
//
|
||||
// reject(stdError);
|
||||
// return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* determines a command exists on host or not ...
|
||||
*
|
||||
* @param {string} name specific command name ...
|
||||
*
|
||||
* @returns boolean Promise ...
|
||||
*/
|
||||
function checkCommandExists(name) {
|
||||
return new Promise(resolve => {
|
||||
//
|
||||
if (!name) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`;
|
||||
execute(cmd).then(result => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(err => {
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region required commands state ...
|
||||
/**
|
||||
* check al required commands exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function isRequiredCommandsExists() {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
// const isTarExists = await isTarCommandExists();
|
||||
// const isCatExists = await isCatCommandExists();
|
||||
// const isGrepExists = await isGrepCommandExists();
|
||||
// const isSedExists = await isSedCommandExists();
|
||||
const isNpmExists = await isNpmCommandExists();
|
||||
const isNgExists = await isNgCommandExists();
|
||||
const isIonicExists = await isIonicCommandExists();
|
||||
const isCordovaExists = await isCordovaCommandExists();
|
||||
|
||||
//
|
||||
result = isNpmExists
|
||||
&& isNgExists
|
||||
&& isIonicExists
|
||||
&& isCordovaExists
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve required commands state object ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function getRequiredCommandsStates() {
|
||||
//
|
||||
const result = {};
|
||||
|
||||
//
|
||||
// const isTarExists = await isTarCommandExists();
|
||||
// const isCatExists = await isCatCommandExists();
|
||||
// const isGrepExists = await isGrepCommandExists();
|
||||
// const isSedExists = await isSedCommandExists();
|
||||
const isNpmExists = await isNpmCommandExists();
|
||||
const isNgExists = await isNgCommandExists();
|
||||
const isIonicExists = await isIonicCommandExists();
|
||||
const isCordovaExists = await isCordovaCommandExists();
|
||||
|
||||
//
|
||||
result['npm'] = isNpmExists;
|
||||
result['ng'] = isNgExists;
|
||||
result['ionic'] = isIonicExists;
|
||||
result['cordova'] = isCordovaExists;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Commonly used Command Checkers ...
|
||||
/**
|
||||
* determines npm command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isNpmCommandExists() {
|
||||
return checkCommandExists('npm');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines ng command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isNgCommandExists() {
|
||||
return checkCommandExists('ng');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines ionic command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isIonicCommandExists() {
|
||||
return checkCommandExists('ionic');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines cordova command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isCordovaCommandExists() {
|
||||
return checkCommandExists('cordova');
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
execute,
|
||||
checkCommandExists,
|
||||
isRequiredCommandsExists,
|
||||
getRequiredCommandsStates,
|
||||
|
||||
//
|
||||
isNgCommandExists,
|
||||
isIonicCommandExists,
|
||||
isCordovaCommandExists,
|
||||
}
|
||||
//#endregion
|
||||
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* DataType Tools Module ...
|
||||
* a module for manipulate and detect supported data types in node js ...
|
||||
*
|
||||
* Maintainer
|
||||
*
|
||||
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
|
||||
*/
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
/**
|
||||
* all supported data types ...
|
||||
*/
|
||||
const DataTypes = {
|
||||
Null: 'null',
|
||||
Date: 'date',
|
||||
Array: 'array',
|
||||
Object: 'object',
|
||||
String: 'string',
|
||||
Number: 'number',
|
||||
Unknown: 'unknown',
|
||||
Boolean: 'boolean',
|
||||
Function: 'function',
|
||||
Undefined: 'undefined',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
/**
|
||||
* detect type of a content ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getType(value) {
|
||||
//
|
||||
const type = typeof value;
|
||||
|
||||
//
|
||||
let result = DataTypes.Unknown;
|
||||
let dateIdentifier = '[object Date]';
|
||||
let constructor = value && value.constructor ?
|
||||
value.constructor.toString() :
|
||||
'';
|
||||
|
||||
//
|
||||
switch (type) {
|
||||
//
|
||||
case 'undefined':
|
||||
result = DataTypes.Undefined;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'boolean':
|
||||
result = DataTypes.Boolean;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'string':
|
||||
result = DataTypes.String;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'number':
|
||||
result = DataTypes.Number;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'function':
|
||||
result = DataTypes.Function;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'object':
|
||||
//
|
||||
// Null ...
|
||||
if (value === null) {
|
||||
result = DataTypes.Null;
|
||||
} else
|
||||
//
|
||||
// Array ...
|
||||
if (Array.isArray(value)) {
|
||||
result = DataTypes.Array;
|
||||
} else
|
||||
//
|
||||
// Data ...
|
||||
if (
|
||||
value instanceof Date ||
|
||||
isFunction(value.getMonth) ||
|
||||
constructor.includes(dateIdentifier) ||
|
||||
Object.prototype.toString.call(value) === dateIdentifier
|
||||
) {
|
||||
result = DataTypes.Date;
|
||||
} else
|
||||
//
|
||||
// Object ...
|
||||
{
|
||||
result = DataTypes.Object;
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
default:
|
||||
result = DataTypes.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve an object constructor ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getConstructor(value) {
|
||||
//
|
||||
const result = value && value.constructor ?
|
||||
value.constructor.toString() :
|
||||
'';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve an object prototype ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getPrototype(value) {
|
||||
//
|
||||
const result = value ?
|
||||
Object.prototype.toString.call(value) :
|
||||
'';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is null or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNull(value) {
|
||||
return getType(value) === DataTypes.Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is undefined or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isUndefined(value) {
|
||||
return getType(value) === DataTypes.Undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is null or undefined or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNullOrUndefined(value) {
|
||||
return isNull(value) || isUndefined(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is a date or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDate(value) {
|
||||
return getType(value) === DataTypes.Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is number or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNumber(value) {
|
||||
return getType(value) === DataTypes.Number;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is string or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isString(value) {
|
||||
return getType(value) === DataTypes.String;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is boolean or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isBoolean(value) {
|
||||
return getType(value) === DataTypes.Boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is an Array or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isArray(value) {
|
||||
return getType(value) === DataTypes.Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is and Object or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isObject(value) {
|
||||
return getType(value) === DataTypes.Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is a Function or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isFunction(value) {
|
||||
return getType(value) === DataTypes.Function;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
DataTypes,
|
||||
|
||||
//
|
||||
getType,
|
||||
getConstructor,
|
||||
getPrototype,
|
||||
isNull,
|
||||
isUndefined,
|
||||
isNullOrUndefined,
|
||||
isDate,
|
||||
isNumber,
|
||||
isString,
|
||||
isBoolean,
|
||||
isArray,
|
||||
isObject,
|
||||
isFunction,
|
||||
}
|
||||
//#endregion
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
EURUSDb,GBPUSDb,USDJPYb,USDCHFb,XAUUSDb|M5,M15|0.01|X786|true
|
||||
@@ -0,0 +1,22 @@
|
||||
const int rates_total, // total calculated Candles on charts ...
|
||||
const int prev_calculated, // total calculated Candles on charts ...
|
||||
const datetime &time[], // history of Candles Open Time ...
|
||||
const double &open[], // history of Candles Open Price ...
|
||||
const double &high[], // history of Candles High Price ...
|
||||
const double &low[], // history of Candles Low Price ...
|
||||
const double &close[], // history of Candles Close Price ...
|
||||
const long &tick_volume[], // history of Tick Volumes on Candle ...
|
||||
const long &volume[], // history of Trade Volumes ...
|
||||
const int &spread[] // history of Candles Spread Price ...
|
||||
|
||||
|
||||
// //
|
||||
// // XICH ...
|
||||
// string ich =
|
||||
// //
|
||||
// "" + "\n" +
|
||||
// "-------------" + "\n" +
|
||||
// (( || !ignoreFalseConditions) ? ": " + ToString() + "\n" : "") +
|
||||
// "\n"
|
||||
// //
|
||||
// ;
|
||||
Binary file not shown.
@@ -0,0 +1,168 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ExpertMACD.mq5 |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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.
@@ -0,0 +1,45 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Controls.mq5 |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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-2024, 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()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,451 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MACD Sample.mq5 |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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-2024, 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-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2000-2024, 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.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user