Files
xMQL5/BKPS/14021004 XEU5/Classes/x-saherelm.class.lib.mq5
T
2024-01-25 04:09:42 +03:30

6321 lines
143 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// --------------------------------------
// Name: XClass
// Description: provides all classes for use ...
//
//
// 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
//
#include <Trade\Trade.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>
//
#include "../Libraries/x-saherelm.draw.lib.mq5"
#include "../Libraries/x-saherelm.alert.lib.mq5"
#include "../Libraries/x-saherelm.models.lib.mq5"
#include "../Libraries/x-saherelm.common.lib.mq5"
//
// START Constant 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 Constant Definitions ...
//
//
// START Model Definitions ...
//
//
string X_SIGNAL_TP = "TP";
string X_SIGNAL_SL = "SL";
string X_SIGNAL_TYPE = "TY";
string X_SIGNAL_TICKET = "T";
string X_SIGNAL_RISKFREE_STEP = "RFS";
string X_SIGNAL_RISKFREE_RATE = "RFR";
//
struct XTraderHandlerResult
{
//
// List Of Closed On SL Signals ...
XSignal sl[];
//
// List Of Closed On TP Signals ...
XSignal tp[];
//
// List Of Risk Free Signals ...
XSignal rf[];
};
//
// Define Volume States ...
struct XVolumeInfo
{
//
// Current Available Static Volume ...
double staticVolume;
//
// Static Volume Calculation Method ...
string staticVolumeCalculationMethod;
//
// Current Maximum Appliable Volume ...
double maxAllowedVolume;
//
// Static Volume Increase Multiplier ...
double volumeIncreaseMultiplier;
//
// Multiply Volume Based On Balance Growing ...
double balanceGowingToApplyMultiplier;
//
// Where to Increase MaxAllowed Volume ...
double balanceGrowingToIncreaseMaxAllowedVolume;
};
//
// Model a Simple Provider Status ...
struct XSignallerInfo
{
//
// Provider Name ...
string name;
//
// Number of Longs ...
int longs;
//
// Number of Shorts ...
int shorts;
};
//
// Model Some of Usefull Signals and Market Data ...
struct XSummaryInfo
{
//
// Define Max Signal Volume ...
double maxSignalVolume;
//
// Max DrawDown ...
double maxDrawDown;
//
// Max DrawUp ...
double maxDrawUp;
//
// Max Number of Same Time Signals ...
int maxSameTimeSignals;
//
// Number of Long Trades ...
int longSignals;
//
// Number of Short Trades ...
int shortSignals;
//
// Number of TPs Attached ...
int numberOfTPs;
//
// Number of SLs Attached ...
int numberOfSLs;
};
//
// Model Account info ...
struct XAccountInfo
{
//
// User Account ...
string user;
//
// Name of Client ...
string name;
//
// Trade Server Name ...
string server;
//
// Broker Name ...
string broker;
//
// Account Trade Mode ...
ENUM_ACCOUNT_TRADE_MODE mode;
//
// Account Leverage ...
long leverage;
//
// Currency ...
string currency;
//
// Deposit ...
double deposit;
//
// Balance ...
double balance;
//
// Min Balance for Open Trades ...
double minBalanceForOpenTrades;
};
//
// this is a Model Which holds Reports for Specific Time Periods ...
struct XReport
{
//
datetime start;
//
datetime end;
//
XAccountInfo accountInfo;
//
XVolumeInfo volumeInfo;
//
XSignallerInfo signallersInfo[];
//
XSummaryInfo summaryInfo;
};
//
// an Enumeration Object which determines Report Type ...
enum ENUM_XREPORT_TYPES
{
//
// Main Report ...
XREPORT_MAIN,
//
// Daily Report ...
XREPORT_DAILY,
//
// Weekly Report ...
XREPORT_WEEKLY,
//
// Monthly Report ...
XREPORT_MONTHLY,
};
//
// END Model Definitions ...
//
//
// START Overrides ...
//
class XSCTrade : public CTrade
{
public:
//
// Modify Specific Position, by Specific Comment ...
bool PositionModify(
const string symbol, // Symbol
const double sl, // Stop Loss
const double tp, // Take Profit
const string comment = "" // Comment For Modify
)
{
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// check position existence
if (!SelectPosition(symbol))
{
return (false);
}
//
// clean
ClearStructures();
//
// setting request
m_request.action = TRADE_ACTION_SLTP;
m_request.symbol = symbol;
m_request.magic = m_magic;
m_request.sl = sl;
m_request.tp = tp;
m_request.position = PositionGetInteger(POSITION_TICKET);
//
// Specified Comment ...
if (StringLen(comment) > 0)
{
m_request.comment = comment;
}
//
// action and return the result
return (OrderSend(m_request, m_result));
}
bool PositionModify(
const ulong ticket, // Position Ticket
const double sl, // Stop Loss
const double tp, // Take Profit
const string comment = "" // Comment For Modify
)
{
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// check position existence
if (!PositionSelectByTicket(ticket))
{
return (false);
}
//
// clean
ClearStructures();
//
// setting request
m_request.action = TRADE_ACTION_SLTP;
m_request.position = ticket;
m_request.symbol = PositionGetString(POSITION_SYMBOL);
m_request.magic = m_magic;
m_request.sl = sl;
m_request.tp = tp;
//
// Specified Comment ...
if (StringLen(comment) > 0)
{
m_request.comment = comment;
}
//
// action and return the result
return (OrderSend(m_request, m_result));
}
//
// Close Specific Position, by Specific Comment ...
bool PositionClose(
const string symbol, // Symbol
const ulong deviation, // Deviation
const string comment = "" // Comment For Close
)
{
//
bool partial_close = false;
int retry_count = 10;
uint retcode = TRADE_RETCODE_REJECT;
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// clean
ClearStructures();
//
// check filling
if (!FillingCheck(symbol))
{
return (false);
}
//
do
{
//
// check
if (SelectPosition(symbol))
{
//
if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
//
// prepare request for close BUY position
m_request.type = ORDER_TYPE_SELL;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
}
else
{
//
// prepare request for close SELL position
m_request.type = ORDER_TYPE_BUY;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK);
}
}
else
{
//
// position not found
m_result.retcode = retcode;
return (false);
}
//
// setting request
m_request.action = TRADE_ACTION_DEAL;
m_request.symbol = symbol;
m_request.volume = PositionGetDouble(POSITION_VOLUME);
m_request.magic = m_magic;
m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation;
m_request.position = PositionGetInteger(POSITION_TICKET);
//
// Specify Comment ...
m_request.comment = comment;
//
// check volume
double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
if (m_request.volume > max_volume)
{
//
m_request.volume = max_volume;
partial_close = true;
}
else
{
partial_close = false;
}
//
// hedging? just send order
if (IsHedging())
{
return (OrderSend(m_request, m_result));
}
//
// order send
if (!OrderSend(m_request, m_result))
{
//
if (--retry_count != 0)
{
continue;
}
//
if (retcode == TRADE_RETCODE_DONE_PARTIAL)
{
m_result.retcode = retcode;
}
//
return (false);
}
//
//--- WARNING. If position volume exceeds the maximum volume allowed for deal,
//--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely,
//--- but partially. It is decreased by the maximum volume allowed for deal.
if (m_async_mode)
{
break;
}
//
retcode = TRADE_RETCODE_DONE_PARTIAL;
if (partial_close)
{
Sleep(1000);
}
} while (partial_close);
//
// succeed
return (true);
}
bool PositionClose(
const ulong ticket, // Position Ticket
const ulong deviation, // Deviation
const string comment = "" // Comment For Close
)
{
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// check position existence
if (!PositionSelectByTicket(ticket))
{
return (false);
}
//
string symbol = PositionGetString(POSITION_SYMBOL);
//
// clean
ClearStructures();
//
// check filling
if (!FillingCheck(symbol))
{
return (false);
}
//
// check
if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
//
// prepare request for close BUY position
m_request.type = ORDER_TYPE_SELL;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
}
else
{
//
// prepare request for close SELL position
m_request.type = ORDER_TYPE_BUY;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK);
}
//
// setting request
m_request.action = TRADE_ACTION_DEAL;
m_request.position = ticket;
m_request.symbol = symbol;
m_request.volume = PositionGetDouble(POSITION_VOLUME);
m_request.magic = m_magic;
m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation;
//
// Specify Comment ...
m_request.comment = comment;
//
// close position
return (OrderSend(m_request, m_result));
}
//
// Partial Close Specific Position, by Specific Comment ...
bool PositionClosePartial(
const string symbol, // Symbol
const double volume, // Partial Closing Volume
const ulong deviation, // Deviation
const string comment = "" // Comment For Close
)
{
//
uint retcode = TRADE_RETCODE_REJECT;
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// for hedging mode only
if (!IsHedging())
{
return (false);
}
//
// clean
ClearStructures();
//
// check filling
if (!FillingCheck(symbol))
{
return (false);
}
//
// check
if (SelectPosition(symbol))
{
//
if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
//
// prepare request for close BUY position
m_request.type = ORDER_TYPE_SELL;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
}
else
{
//
// prepare request for close SELL position
m_request.type = ORDER_TYPE_BUY;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK);
}
}
else
{
//
// position not found
m_result.retcode = retcode;
return (false);
}
//
// check volume
double position_volume = PositionGetDouble(POSITION_VOLUME);
if (position_volume > volume)
{
position_volume = volume;
}
//
// setting request
m_request.action = TRADE_ACTION_DEAL;
m_request.symbol = symbol;
m_request.volume = position_volume;
m_request.magic = m_magic;
m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation;
m_request.position = PositionGetInteger(POSITION_TICKET);
//
// Specifieng Comment ...
m_request.comment = comment;
//
// hedging? just send order
return (OrderSend(m_request, m_result));
}
bool PositionClosePartial(
const ulong ticket, // Position Ticket
const double volume, // Partial Closing Volume
const ulong deviation, // Deviation
const string comment = "" // Comment For Close
)
{
//
// check stopped
if (IsStopped(__FUNCTION__))
{
return (false);
}
//
// for hedging mode only
if (!IsHedging())
{
return (false);
}
//
// check position existence
if (!PositionSelectByTicket(ticket))
{
return (false);
}
//
string symbol = PositionGetString(POSITION_SYMBOL);
//
// clean
ClearStructures();
//
// check filling
if (!FillingCheck(symbol))
{
return (false);
}
//
// check
if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
//
// prepare request for close BUY position
m_request.type = ORDER_TYPE_SELL;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
}
else
{
//
// prepare request for close SELL position
m_request.type = ORDER_TYPE_BUY;
m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK);
}
//
// check volume
double position_volume = PositionGetDouble(POSITION_VOLUME);
if (position_volume > volume)
{
position_volume = volume;
}
//
// setting request
m_request.action = TRADE_ACTION_DEAL;
m_request.position = ticket;
m_request.symbol = symbol;
m_request.volume = position_volume;
m_request.magic = m_magic;
m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation;
//
// Specifieng Comment ...
m_request.comment = comment;
//
// close position
return (OrderSend(m_request, m_result));
}
};
//
// END Overrides ...
//
//
// XCMD5 a library for Hashing ...
class XCMD5
{
//
// Public Provides ...
public:
//
// Protected Provides ...
//
// Constructor ...
XCMD5(void) {}
//
// Deconstructor ...
~XCMD5(void) {}
//
// Hash Specified Char Array ...
string Hash(
uchar &source[], // Specify Char Array to Hash
int length = 0 // Specify Length of Char Array which required to hash
)
{
//
string result = "";
//
int sourceCount = ArraySize(source);
//
// Validate Args ...
if (
sourceCount <= 0 ||
(sourceCount > 0 && length > sourceCount))
{
return result;
}
//
// Normalize Args ...
if (length == 0)
{
length = sourceCount;
}
//
// Init MD5 ...
MD5Init();
//
// Update Buffer ...
MD5Update(source, length);
//
// Calculate Result ...
result = MD5Final();
//
return result;
}
//
// Hash Specified String ...
string Hash(
string source // Specified String
)
{
//
string result = "";
//
// Converts String to Char Array ...
uchar bytes[];
StringToCharArray(
source,
bytes,
0,
StringLen(source));
//
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;
}
};
//
// XSaherElm Account Info Class ...
class XCAccountInfo
{
//
// Public properties ...
public:
//
// Constructro ...
void XCAccountInfo()
{
//
mAccountInfo = new CAccountInfo();
//
mInitialBalance = mAccountInfo.Balance();
}
//
// Deconstructor ...
void ~XCAccountInfo()
{
//
mInitialBalance = 0;
}
//
// 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 Initial Deposit Balance ...
double GetInitialBalance()
{
return mInitialBalance;
}
//
// 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;
}
//
// Protected properties ...
protected:
//
// Private properties ...
private:
//
// Initial Account Balance ...
double mInitialBalance;
//
// Account Info ...
CAccountInfo mAccountInfo;
};
//
// XSaherElm Report Info Class ...
class XCReporter
{
//
// Public Provided ...
public:
//
// Constructro ...
void XCReporter()
{
//
mAccountInfo = new XCAccountInfo();
//
ResetReports();
}
//
// Deconstructor ...
void ~XCReporter()
{
}
//
// Reset Specific Report ...
void ResetReport(
ENUM_XREPORT_TYPES type // Specify Report Type
)
{
CleanReport(type);
}
//
// Reset All Reports ...
void ResetReports()
{
//
CleanReport(XREPORT_MAIN);
CleanReport(XREPORT_MONTHLY);
CleanReport(XREPORT_WEEKLY);
CleanReport(XREPORT_DAILY);
}
//
// Update Volume Info ...
void UpdateReportVolumeInfo(
ENUM_XREPORT_TYPES type, // Specified Report Type
//
double staticVolume, // Current Available Static Volume
string staticVolumeCalculationMethod, // Static Volume Calculation Method
double maxAllowedVolume, // Current Maximum Appliable Volume
double volumeIncreaseMultiplier, // Static Volume Increase Multiplier
double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing
double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume
)
{
//
// Filling Account Info ...
FillReportAccountInfo(type);
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
//
FillingVolumeInfo(
mMainReport,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
//
FillingVolumeInfo(
mMonthlyReport,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
//
FillingVolumeInfo(
mWeeklyReport,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
break;
//
// Daily ...
case XREPORT_DAILY:
//
FillingVolumeInfo(
mDailyReport,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
break;
}
}
//
// Update Volume Info on All Reports ...
void UpdateReportsVolumeInfo(
double staticVolume, // Current Available Static Volume
string staticVolumeCalculationMethod, // Static Volume Calculation Method
double maxAllowedVolume, // Current Maximum Appliable Volume
double volumeIncreaseMultiplier, // Static Volume Increase Multiplier
double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing
double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume
)
{
//
// Main ...
UpdateReportVolumeInfo(
XREPORT_MAIN,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
//
// Monthly ...
UpdateReportVolumeInfo(
XREPORT_MONTHLY,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
//
// Weekly ...
UpdateReportVolumeInfo(
XREPORT_WEEKLY,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
//
// Daily ...
UpdateReportVolumeInfo(
XREPORT_DAILY,
staticVolume,
staticVolumeCalculationMethod,
maxAllowedVolume,
volumeIncreaseMultiplier,
balanceGowingToApplyMultiplier,
balanceGrowingToIncreaseMaxAllowedVolume);
}
//
// Add Specific Signal to Report ...
void AddSignalToReport(
ENUM_XREPORT_TYPES type, // Specified Report Type
const XSignal &signal, // Specified Signal
const string &providers[] // Specified Signal Providers
)
{
//
//
// Filling Account Info ...
FillReportAccountInfo(type);
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
AddSignalToReport(
mMainReport,
signal,
providers);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
AddSignalToReport(
mMonthlyReport,
signal,
providers);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
AddSignalToReport(
mWeeklyReport,
signal,
providers);
break;
//
// Daily ...
case XREPORT_DAILY:
AddSignalToReport(
mDailyReport,
signal,
providers);
break;
}
}
//
// Add Specific Signal to All Reports ...
void AddSignalToReports(
const XSignal &signal, // Specified Signal
const string &providers[] // Specified Signal Providers
)
{
//
// Main ...
AddSignalToReport(
XREPORT_MAIN,
signal,
providers);
//
// Monthly ...
AddSignalToReport(
XREPORT_MONTHLY,
signal,
providers);
//
// Weekly ...
AddSignalToReport(
XREPORT_WEEKLY,
signal,
providers);
//
// Daily ...
AddSignalToReport(
XREPORT_DAILY,
signal,
providers);
}
//
// Report a TP for Specific Report ...
void AddTradeTPInReport(
ENUM_XREPORT_TYPES type // Specified Report Type
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
AddTradeTPInReport(mMainReport);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
AddTradeTPInReport(mMonthlyReport);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
AddTradeTPInReport(mWeeklyReport);
break;
//
// Daily ...
case XREPORT_DAILY:
AddTradeTPInReport(mDailyReport);
break;
}
}
//
// Report a TP for All Reports ...
void AddTradeTPInReports()
{
//
// Main ...
AddTradeTPInReport(XREPORT_MAIN);
//
// Monthly ...
AddTradeTPInReport(XREPORT_MONTHLY);
//
// Weekly ...
AddTradeTPInReport(XREPORT_WEEKLY);
//
// Daily ...
AddTradeTPInReport(XREPORT_DAILY);
}
//
// Report a SL for Specific Report ...
void AddTradeSLInReport(
ENUM_XREPORT_TYPES type // Specified Report Type
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
AddTradeSLInReport(mMainReport);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
AddTradeSLInReport(mMonthlyReport);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
AddTradeSLInReport(mWeeklyReport);
break;
//
// Daily ...
case XREPORT_DAILY:
AddTradeSLInReport(mDailyReport);
break;
}
}
//
// Report a SL for All Reports ...
void AddTradeSLInReports()
{
//
// Main ...
AddTradeSLInReport(XREPORT_MAIN);
//
// Monthly ...
AddTradeSLInReport(XREPORT_MONTHLY);
//
// Weekly ...
AddTradeSLInReport(XREPORT_WEEKLY);
//
// Daily ...
AddTradeSLInReport(XREPORT_DAILY);
}
//
// Update Number of Same Time Trades in Specific Report ...
void UpdateMaxSameTimeTradesInReport(
ENUM_XREPORT_TYPES type, // Specified Report Type
int value // number of same time trades
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
UpdateMaxSameTimeTradesInReport(
mMainReport,
value);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
UpdateMaxSameTimeTradesInReport(
mMonthlyReport,
value);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
UpdateMaxSameTimeTradesInReport(
mWeeklyReport,
value);
break;
//
// Daily ...
case XREPORT_DAILY:
UpdateMaxSameTimeTradesInReport(
mDailyReport,
value);
break;
}
}
//
// Update Number of Same Time Trades in All Report ...
void UpdateMaxSameTimeTradesInReports(
int value // number of same time trades
)
{
//
// Main ...
UpdateMaxSameTimeTradesInReport(
XREPORT_MAIN,
value);
//
// Monthly ...
UpdateMaxSameTimeTradesInReport(
XREPORT_MONTHLY,
value);
//
// Weekly ...
UpdateMaxSameTimeTradesInReport(
XREPORT_WEEKLY,
value);
//
// Daily ...
UpdateMaxSameTimeTradesInReport(
XREPORT_DAILY,
value);
}
//
// Update Max DrawDown in Specific Report ...
void UpdateMaxDrawDownInReport(
ENUM_XREPORT_TYPES type, // Specified Report Type
double value // draw down value
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
UpdateMaxDrawDownInReport(
mMainReport,
value);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
UpdateMaxDrawDownInReport(
mMonthlyReport,
value);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
UpdateMaxDrawDownInReport(
mWeeklyReport,
value);
break;
//
// Daily ...
case XREPORT_DAILY:
UpdateMaxDrawDownInReport(
mDailyReport,
value);
break;
}
}
//
// Update Max DrawDown in All Report ...
void UpdateMaxDrawDownInReports(
double value // draw down value
)
{
//
// Main ...
UpdateMaxDrawDownInReport(
XREPORT_MAIN,
value);
//
// Monthly ...
UpdateMaxDrawDownInReport(
XREPORT_MONTHLY,
value);
//
// Weekly ...
UpdateMaxDrawDownInReport(
XREPORT_WEEKLY,
value);
//
// Daily ...
UpdateMaxDrawDownInReport(
XREPORT_DAILY,
value);
}
//
// Update Max DrawUp in Specific Report ...
void UpdateMaxDrawUpInReport(
ENUM_XREPORT_TYPES type, // Specified Report Type
double value // draw up value
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
UpdateMaxDrawUpInReport(
mMainReport,
value);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
UpdateMaxDrawUpInReport(
mMonthlyReport,
value);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
UpdateMaxDrawUpInReport(
mWeeklyReport,
value);
break;
//
// Daily ...
case XREPORT_DAILY:
UpdateMaxDrawUpInReport(
mDailyReport,
value);
break;
}
}
//
// Update Max DrawUp in All Report ...
void UpdateMaxDrawUpInReports(
double value // draw up value
)
{
//
// Main ...
UpdateMaxDrawUpInReport(
XREPORT_MAIN,
value);
//
// Monthly ...
UpdateMaxDrawUpInReport(
XREPORT_MONTHLY,
value);
//
// Weekly ...
UpdateMaxDrawUpInReport(
XREPORT_WEEKLY,
value);
//
// Daily ...
UpdateMaxDrawUpInReport(
XREPORT_DAILY,
value);
}
//
// Update Min Balance for Open Trades in Specific Report ...
void UpdateMinBalanceForOpenTradesInReport(
ENUM_XREPORT_TYPES type, // Specified Report Type
double value // min balance for open trades
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
UpdateMinBalanceForOpenTradesInReport(
mMainReport,
value);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
UpdateMinBalanceForOpenTradesInReport(
mMonthlyReport,
value);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
UpdateMinBalanceForOpenTradesInReport(
mWeeklyReport,
value);
break;
//
// Daily ...
case XREPORT_DAILY:
UpdateMinBalanceForOpenTradesInReport(
mDailyReport,
value);
break;
}
}
//
// Update Min Balance for Open Trades in All Report ...
void UpdateMinBalanceForOpenTradesInReports(
double value // min balance for open trades
)
{
//
// Main ...
UpdateMinBalanceForOpenTradesInReport(
XREPORT_MAIN,
value);
//
// Monthly ...
UpdateMinBalanceForOpenTradesInReport(
XREPORT_MONTHLY,
value);
//
// Weekly ...
UpdateMinBalanceForOpenTradesInReport(
XREPORT_WEEKLY,
value);
//
// Daily ...
UpdateMinBalanceForOpenTradesInReport(
XREPORT_DAILY,
value);
}
//
// Gnerate Specific Type Of Report String Representation ...
string GenerateReportString(
ENUM_XREPORT_TYPES type, // Specified Report Type
string separator = "\n" // Separator
)
{
//
string result = "";
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
result = GenerateReportString(
mMainReport,
separator);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
result = GenerateReportString(
mMonthlyReport,
separator);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
result = GenerateReportString(
mWeeklyReport,
separator);
break;
//
// Daily ...
case XREPORT_DAILY:
result = GenerateReportString(
mDailyReport,
separator);
break;
}
//
return result;
}
//
// Protected Provided ...
protected:
//
// Private Provided ...
private:
//
// Account Info Instance ...
XCAccountInfo mAccountInfo;
//
// Main Report ...
XReport mMainReport;
//
// Monthly Report ...
XReport mMonthlyReport;
//
// Weekly Report ...
XReport mWeeklyReport;
//
// Daily Report ...
XReport mDailyReport;
//
// Clean Specific Report ...
void CleanReport(
XReport &report // Specified Report
)
{
//
datetime time = TimeCurrent();
//
// Reset Times ...
report.start = time;
report.end = -1;
//
// Reset Account Info ...
FillReportAccountInfo(report);
//
// Reset Summary Info ...
report.summaryInfo.maxDrawUp = 0;
report.summaryInfo.maxDrawDown = 0;
report.summaryInfo.longSignals = 0;
report.summaryInfo.numberOfTPs = 0;
report.summaryInfo.numberOfSLs = 0;
report.summaryInfo.shortSignals = 0;
report.summaryInfo.maxSignalVolume = 0;
report.summaryInfo.maxSameTimeSignals = 0;
//
// Reset Volume Info ...
report.volumeInfo.staticVolume = 0;
report.volumeInfo.maxAllowedVolume = 0;
report.volumeInfo.volumeIncreaseMultiplier = 0;
report.volumeInfo.balanceGowingToApplyMultiplier = 0;
report.volumeInfo.staticVolumeCalculationMethod = NULL;
report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = 0;
//
// Reset Signallers Info ...
CleanBuffer(report.signallersInfo);
}
void CleanReport(
ENUM_XREPORT_TYPES type // Specify Report Type
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
CleanReport(mMainReport);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
CleanReport(mMonthlyReport);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
CleanReport(mWeeklyReport);
break;
//
// Daily ...
case XREPORT_DAILY:
CleanReport(mDailyReport);
break;
}
}
//
// Update Specific Reports End Time ...
void FillReportEndTime(
XReport &report // Specified Report
)
{
//
datetime time = TimeCurrent();
report.end = time;
}
//
// Filleing Report Account Info ...
void FillReportAccountInfo(
XReport &report // Specified Report
)
{
//
FillReportEndTime(report);
//
report.accountInfo.user = (string)mAccountInfo.GetUserAccount();
report.accountInfo.name = mAccountInfo.GetName();
report.accountInfo.server = mAccountInfo.GetServerName();
report.accountInfo.broker = mAccountInfo.GetCompany();
report.accountInfo.mode = mAccountInfo.GetTradeMode();
report.accountInfo.leverage = mAccountInfo.GetLeverage();
report.accountInfo.currency = mAccountInfo.GetCurrency();
report.accountInfo.deposit = mAccountInfo.GetInitialBalance();
report.accountInfo.balance = mAccountInfo.GetBalance();
}
void FillReportAccountInfo(
ENUM_XREPORT_TYPES type // Specify Report Type
)
{
//
switch (type)
{
//
// Main ...
case XREPORT_MAIN:
FillReportAccountInfo(mMainReport);
break;
//
// Monthly ...
case XREPORT_MONTHLY:
FillReportAccountInfo(mMonthlyReport);
break;
//
// Weekly ...
case XREPORT_WEEKLY:
FillReportAccountInfo(mWeeklyReport);
break;
//
// Daily ...
case XREPORT_DAILY:
FillReportAccountInfo(mDailyReport);
break;
}
}
//
// Filling Volume Info ...
void FillingVolumeInfo(
XReport &report, // Specified Report
//
double staticVolume, // Current Available Static Volume
string staticVolumeCalculationMethod, // Static Volume Calculation Method
double maxAllowedVolume, // Current Maximum Appliable Volume
double volumeIncreaseMultiplier, // Static Volume Increase Multiplier
double balanceGowingToApplyMultiplier, // Multiply Volume Based On Balance Growing
double balanceGrowingToIncreaseMaxAllowedVolume // Where to Increase MaxAllowed Volume
)
{
//
FillReportEndTime(report);
//
report.volumeInfo.staticVolume = staticVolume;
report.volumeInfo.maxAllowedVolume = maxAllowedVolume;
report.volumeInfo.volumeIncreaseMultiplier = volumeIncreaseMultiplier;
report.volumeInfo.staticVolumeCalculationMethod = staticVolumeCalculationMethod;
report.volumeInfo.balanceGowingToApplyMultiplier = balanceGowingToApplyMultiplier;
report.volumeInfo.balanceGrowingToIncreaseMaxAllowedVolume = balanceGrowingToIncreaseMaxAllowedVolume;
}
//
// Add Signal to Report ...
void AddSignalToReport(
XReport &report, // Specified Report
const XSignal &signal, // Specified Signal
const string &providers[] // Specified Signal Providers
)
{
//
FillReportEndTime(report);
//
double volume = signal.volume;
bool isLong = signal.type == X_SIGNAL_LONG;
//
// Update Longs and Shorts ...
if (isLong)
{
report.summaryInfo.longSignals++;
}
else
{
report.summaryInfo.shortSignals++;
}
//
// Chack Max Volume ...
if (volume > report.summaryInfo.maxSignalVolume)
{
report.summaryInfo.maxSignalVolume = volume;
}
//
// Update Signallers Info ...
for (int i = 0; i < ArraySize(providers); i++)
{
//
string iProvider = providers[i];
//
AddOrUpdateSignaller(
report,
iProvider,
signal);
}
}
//
// Add or Update Signaller Info of Specific Report ...
void AddOrUpdateSignaller(
XReport &report, // Specified Report
const string provider, // Signal Provider name
const XSignal &signal // Specified Signal
)
{
//
int providerIdx = -1;
int signallersInfoCount = 0;
bool isLong = signal.type == X_SIGNAL_LONG;
//
// Prepare New One Provider ...
XSignallerInfo info = {};
info.name = provider;
if (isLong)
{
info.longs = 1;
}
else
{
info.shorts = 1;
}
//
// Find Provider idx if Exists ...
providerIdx = FindProviderInSignallersInfo(
provider,
report.signallersInfo);
//
// Check IDX ...
if (providerIdx > -1)
{
//
// Update Exists ...
if (isLong)
{
report.signallersInfo[providerIdx].longs++;
}
else
{
report.signallersInfo[providerIdx].shorts++;
}
}
else
{
//
// Add New One ...
Add(
info,
report.signallersInfo);
}
}
//
// Add TP in Report ...
void AddTradeTPInReport(
XReport &report // Specified Report
)
{
//
FillReportEndTime(report);
//
report.summaryInfo.numberOfTPs++;
}
//
// Add SL in Report ...
void AddTradeSLInReport(
XReport &report // Specified Report
)
{
//
FillReportEndTime(report);
//
report.summaryInfo.numberOfSLs++;
}
//
// Update Number of Same Time Trades in Report ...
void UpdateMaxSameTimeTradesInReport(
XReport &report, // Specified Report
int value // number of same time trades
)
{
//
// Validate Args ...
if (value <= report.summaryInfo.maxSameTimeSignals)
{
return;
}
//
FillReportEndTime(report);
//
report.summaryInfo.maxSameTimeSignals = value;
}
//
// Update Number of Same Time Trades in Report ...
void UpdateMaxDrawUpInReport(
XReport &report, // Specified Report
double value // draw up value
)
{
//
// Validate Args ...
if (value <= report.summaryInfo.maxDrawUp)
{
return;
}
//
FillReportEndTime(report);
//
report.summaryInfo.maxDrawUp = value;
}
//
// Update Number of Same Time Trades in Report ...
void UpdateMaxDrawDownInReport(
XReport &report, // Specified Report
double value // draw down value
)
{
//
// Validate Args ...
if (value <= report.summaryInfo.maxDrawDown)
{
return;
}
//
FillReportEndTime(report);
//
report.summaryInfo.maxDrawDown = value;
}
//
// Update Min Balance for Open Trades Value in Report ...
void UpdateMinBalanceForOpenTradesInReport(
XReport &report, // Specified Report
double value // min balance for open trades
)
{
//
// Validate Arg ...
if (value <= 0)
{
return;
}
//
FillReportEndTime(report);
//
report.accountInfo.minBalanceForOpenTrades = value;
}
//
// Generate Specific Report String Representation ...
string GenerateReportString(
XReport &report, // Specified Report
string separator = "\n" // Separator
)
{
//
string result = "";
//
// Start and End Date ...
result += "Start: " + (string)report.start + separator;
result += "End: " + (string)report.end + separator;
//
// Account Info ...
string accountStr = GenerateAccountInfoReportString(report.accountInfo);
result += "Account: " + separator + accountStr + separator;
//
// Summary Info ...
string summaryStr = GenerateSummaryInfoReportString(report.summaryInfo);
result += "Summary: " + separator + summaryStr + separator;
//
// Volume Info ...
string volumeStr = GenerateVolumeInfoReportString(report.volumeInfo);
result += "Volume: " + separator + volumeStr + separator;
//
// Signallers Info ...
string signallersStr = GenerateSignallersInfoReportString(report.signallersInfo);
result += "Signallers: " + separator + signallersStr + separator;
//
return result;
}
//
// Generate Account info String Representation ...
string GenerateAccountInfoReportString(
XAccountInfo &info, // Specified Account Info
string separator = "\n" // Separator
)
{
//
string result = "";
//
// Generate Report ...
result += "user: " + info.user + separator;
result += "name: " + info.name + separator;
result += "server: " + info.server + separator;
result += "broker: " + info.broker + separator;
result += "mode: " + EnumToString(info.mode) + separator;
result += "leverage: " + (string)info.leverage + separator;
result += "currency: " + info.currency + separator;
result += "deposit: " + (string)info.deposit + separator;
result += "balance: " + (string)info.balance + separator;
result += "minBalanceForTrading: " + (string)info.minBalanceForOpenTrades + separator;
//
return result;
}
//
// Generate Summary info String Representation ...
string GenerateSummaryInfoReportString(
XSummaryInfo &info, // Specified Summary Info
string separator = "\n" // Separator
)
{
//
string result = "";
//
// Generate Report ...
result += "longSignals: " + (string)info.longSignals + separator;
result += "shortSignals: " + (string)info.shortSignals + separator;
result += "numberOfTps: " + (string)info.numberOfTPs + separator;
result += "numberOfSLs: " + (string)info.numberOfSLs + separator;
result += "maxDrawUp: " + (string)info.maxDrawUp + separator;
result += "maxDrawDown: " + (string)info.maxDrawDown + separator;
result += "maxSignalVolume: " + (string)info.maxSignalVolume + separator;
result += "maxSameTimeSignals: " + (string)info.maxSameTimeSignals + separator;
//
return result;
}
//
// Generate Volume info String Representation ...
string GenerateVolumeInfoReportString(
XVolumeInfo &info, // Specified Volume Info
string separator = "\n" // Separator
)
{
//
string result = "";
//
// Generate Report ...
result += "staticVolume: " + (string)info.staticVolume + separator;
result += "staticVolumeCalculationMethod: " + info.staticVolumeCalculationMethod + separator;
result += "maxAllowedVolume: " + (string)info.maxAllowedVolume + separator;
result += "volumeIncreaseMultiplier: " + (string)info.volumeIncreaseMultiplier + separator;
result += "balanceGowingToApplyMultiplier: " + (string)info.balanceGowingToApplyMultiplier + separator;
result += "balanceGrowingToIncreaseMaxAllowedVolume: " + (string)info.balanceGrowingToIncreaseMaxAllowedVolume + separator;
//
return result;
}
//
// Generate Signallers info String Representation ...
string GenerateSignallersInfoReportString(
XSignallerInfo &infos[], // Specified Signallers Info
string separator = "\n" // Separator
)
{
//
string result = "";
//
// Validate Signallers Array Size ...
int signallersCount = ArraySize(infos);
if (signallersCount <= 0)
{
//
result += "EMPTY" + separator;
return result;
}
//
// Generate Report ...
for (int i = 0; i < signallersCount; i++)
{
//
XSignallerInfo iSignaller = infos[i];
//
result += "name: " + iSignaller.name + separator;
result += "longs: " + (string)iSignaller.longs + separator;
result += "shorts: " + (string)iSignaller.shorts + separator;
//
if (i < signallersCount - 1)
{
result += separator;
}
}
//
return result;
}
//
// Add New SignallerInfo to List ...
void Add(
XSignallerInfo &item,
XSignallerInfo &buffer[])
{
//
ArrayResize(
buffer,
ArraySize(buffer) + 1);
//
buffer[ArraySize(buffer) - 1] = item;
}
//
// Clean Signaller Info Buffer ...
void CleanBuffer(XSignallerInfo &buffer[])
{
//
ArrayFree(buffer);
ArrayResize(buffer, 0);
}
//
// Copy Signaller Info ...
void CopyBuffer(
const XSignallerInfo &source[], // Source Buffer ...
XSignallerInfo &dest[] // Dest Buffer ...
)
{
//
CleanBuffer(dest);
//
int sourceCount = ArraySize(source);
if (sourceCount <= 0)
{
return;
}
//
// Loop ...
for (int i = 0; i < sourceCount; i++)
{
//
XSignallerInfo iInfo = source[i];
//
Add(
iInfo,
dest);
}
}
//
// Find a Provider Index in SignallersInfo ...
int FindProviderInSignallersInfo(
string provider, // Specified Provider Name ...
XSignallerInfo &infoBuffer[] // Specified XSignallerInfo Buffer ...
)
{
//
int result = -1;
//
int bufferSize = ArraySize(infoBuffer);
if (bufferSize <= 0)
{
return result;
}
//
// Loop through buffer to find provider index ...
for (int i = 0; i < bufferSize; i++)
{
//
XSignallerInfo iInfo = infoBuffer[i];
//
if (iInfo.name != provider)
{
continue;
}
//
result = i;
}
//
return result;
}
};
//
// a Class For Managing Signals Additional Data ...
class XCSignalManager
{
//
// Public ...
public:
//
// Constructor ...
XCSignalManager(void)
{
CleanData();
}
//
// Deconstructor ...
~XCSignalManager(void) {}
//
// Retrieve All Signals ...
void GetAll(
XSignal &result[] // Hold's Result
)
{
//
CleanBuffer(result);
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
AddItemToBuffer(
iSignal,
result);
}
}
//
// Count Items ...
int Count()
{
return ArraySize(mSignals);
}
//
// Retrieve Specific Signal by Ticket ...
XSignal Get(
ulong ticket // Signals Ticket ...
)
{
//
XSignal result = {};
//
// Check Exists ...
bool isExists = IsExists(ticket);
if (!isExists)
{
return result;
}
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return result;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
if (iSignal.ticket == ticket)
{
//
result = iSignal;
break;
}
}
//
return result;
}
//
// Check Signal Exists or not ...
bool IsExists(
ulong ticket // Specified Signal Ticket
)
{
//
bool result = false;
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return result;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
if (iSignal.ticket == ticket)
{
//
result = true;
break;
}
}
//
return result;
}
bool IsExists(
XSignal &signal // Specified Signal
)
{
//
bool result = false;
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return result;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
if (iSignal.ticket == signal.ticket)
{
//
result = true;
break;
}
}
//
return result;
}
//
// Add Signal ...
bool Add(
XSignal &signal // Specified Signal
)
{
//
bool result = false;
//
// Validate Args ...
if (signal.ticket <= 0)
{
return result;
}
//
// Chekc Signal Exists ...
bool isExists = IsExists(signal);
if (isExists)
{
return result;
}
//
AddItemToBuffer(
signal,
mSignals);
result = true;
//
return result;
}
//
// Update Specific Buffer ...
bool Update(
XSignal &signal // Specified Signal
)
{
//
bool result = false;
//
// Validate Args ...
if (signal.ticket <= 0)
{
return result;
}
//
// Chekc Signal Exists ...
bool isExists = IsExists(signal);
if (!isExists)
{
return result;
}
//
// Remove Signal ...
Remove(signal);
//
// Add new One ...
AddItemToBuffer(
signal,
mSignals);
//
result = true;
//
return result;
}
//
// Remove Signal ...
void Remove(
ulong ticket // Specified Signal Ticket
)
{
//
// Check Signal Exists ...
bool isExists = IsExists(ticket);
if (!isExists)
{
return;
}
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return;
}
//
XSignal signals[];
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
if (iSignal.ticket != ticket)
{
AddItemToBuffer(
iSignal,
signals);
}
}
//
// Now we have to Clean All Signals and Replace them by signals[] buffer ...
UpdateData(signals);
}
void Remove(
XSignal &signal // Specified Signal
)
{
//
// Check Signal Exists ...
bool isExists = IsExists(signal);
if (!isExists)
{
return;
}
//
int signalsCount = ArraySize(mSignals);
if (signalsCount <= 0)
{
return;
}
//
XSignal signals[];
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = mSignals[i];
//
if (iSignal.ticket != signal.ticket)
{
AddItemToBuffer(
iSignal,
signals);
}
}
//
// Now we have to Clean All Signals and Replace them by signals[] buffer ...
UpdateData(signals);
}
//
// Add Or Update ...
bool AddOrUpdate(
XSignal &signal // Specified Signal
)
{
//
bool result = false;
//
// Validate Args ...
if (signal.ticket <= 0)
{
return result;
}
//
// Chekc Signal Exists ...
bool isExists = IsExists(signal);
if (!isExists)
{
result = Add(signal);
}
else
{
result = Update(signal);
}
//
return result;
}
//
// Protected ...
protected:
//
// Private ...
private:
//
// Holds Signals ...
XSignal mSignals[];
//
// Clean All Exists Data ...
void CleanData()
{
CleanBuffer(mSignals);
}
//
// Update Data ...
void UpdateData(
XSignal &source[] // a Buffer which needs to Replace ...
)
{
//
CleanData();
//
int sourceCount = ArraySize(source);
if (sourceCount <= 0)
{
return;
}
//
for (int i = 0; i < sourceCount; i++)
{
//
XSignal iSignal = source[i];
//
AddItemToBuffer(
iSignal,
mSignals);
}
}
//
void AddItemToBuffer(
XSignal &item,
XSignal &buffer[])
{
//
ArrayResize(
buffer,
ArraySize(buffer) + 1);
//
buffer[ArraySize(buffer) - 1] = item;
}
};
//
// START Global Definitions: Variables, Properties and etc ...
//
//
// XSaherElm Trade Class ...
class XCTrade
{
//
// all public features ...
public:
//
// Constructor ...
void XCTrade(
string tag, // Specify a Tag for Trader instance
string symbol, // Specify Trader Symbol
int slippage, // Specify Slippage
ulong magicNumber, // Specify Magic Number
int maxAllowedTrades, // Specify Max Allowed Trades
double minBallanceForOpenTrades, // Specify Minimum Balance for Open Trades
double minAllowedFreeMarginForOpenTrades // Specify Minimum Free Marging for Open Trades
)
{
//
mTag = tag;
mSymbol = symbol;
mSlippage = slippage;
mMagicNumber = magicNumber;
mMaxAllowedTrades = maxAllowedTrades;
mMinBallanceForOpenTrades = minBallanceForOpenTrades;
mMinAllowedFreeMarginForOpenTrades = minAllowedFreeMarginForOpenTrades;
//
mTrader = new XSCTrade();
//
mTrader.SetAsyncMode(false);
mTrader.SetDeviationInPoints(mSlippage);
mTrader.SetExpertMagicNumber(mMagicNumber);
//
// Setting Log Level ...
mTrader.LogLevel(LOG_LEVEL_ERRORS);
//
mSignalManager = new XCSignalManager();
}
//
// Deconstructor ...
void ~XCTrade()
{
}
//
// START Configuring Class Functions ...
//
//
// Update Min Balance For Trading ...
bool SetMinBalanceForTradingPrice(
double price // Specified Price for use as Min Account Balance for Trading
)
{
//
bool result = false;
//
// Validate Arg ...
result = price > mMinBallanceForOpenTrades;
if (!result)
{
return result;
}
//
mMinBallanceForOpenTrades = price;
//
return result;
}
//
// END Configuring Class Functions ...
//
//
// START Count ...
//
//
// Count Open Positions ...
int Count()
{
//
int result = 0;
//
int total = PositionsTotal();
for (int i = 0; i < total; i++)
{
//
if (!mPositionInfo.SelectByIndex(i))
{
continue;
}
//
if (mPositionInfo.Magic() != mMagicNumber)
{
continue;
}
//
if (mPositionInfo.Symbol() != mSymbol)
{
continue;
}
//
result++;
}
//
return result;
}
//
// Count Longs ...
int CountLongs()
{
int result = CountByType(X_SIGNAL_LONG);
return result;
}
//
// Count Shorts ...
int CountShorts()
{
int result = CountByType(X_SIGNAL_SHORT);
return result;
}
//
// Count Specific Type Of Positions ...
int CountByType(ENUM_POSITION_TYPE type)
{
//
int result = 0;
//
int total = PositionsTotal();
for (int i = 0; i < total; i++)
{
//
if (!mPositionInfo.SelectByIndex(i))
{
continue;
}
//
if (mPositionInfo.Symbol() != mSymbol)
{
continue;
}
//
if (mPositionInfo.PositionType() != type)
{
continue;
}
//
result++;
}
//
return result;
}
//
// Count By Type ...
int CountByType(ENUM_X_SIGNAL_TYPE type)
{
//
// Validate Args ...
ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY;
if (type == X_SIGNAL_LONG)
{
mType = POSITION_TYPE_BUY;
}
else if (type == X_SIGNAL_SHORT)
{
mType = POSITION_TYPE_SELL;
}
//
int result = CountByType(mType);
return result;
}
//
// END Count ...
//
//
// START Retrieve ...
//
//
// Retrieve Specified Position by it's Ticket ...
XSignal GetSignal(
ulong ticket // Specified Ticket
)
{
//
XSignal result = {};
//
result = PositionToSignal(ticket);
//
return result;
}
//
// Get Last Signal ...
XSignal GetLastSignal()
{
//
XSignal result = {};
//
XSignal signals[];
GetSignals(signals);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
result = signals[0];
//
return result;
}
//
// Retrieve Last Executed Signal ...
bool GetLastSignal(XSignal &signal)
{
//
bool result = false;
//
XSignal signals[];
GetSignals(signals);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
signal = signals[0];
result = true;
//
return result;
}
//
// Retrieve All Positions ...
void GetSignals(
XSignal &result[] // Holds Result ...
)
{
//
CleanBuffer(result);
//
int totalPositions = PositionsTotal();
for (int i = 0; i < totalPositions; i++)
{
//
if (!mPositionInfo.SelectByIndex(i))
{
continue;
}
//
if (mPositionInfo.Magic() != mMagicNumber)
{
continue;
}
//
if (mPositionInfo.Symbol() != mSymbol)
{
continue;
}
//
// Position to Signal ...
XSignal signal = PositionToSignal(i);
Add(
signal,
result);
}
}
//
// Retrieve Type Specific Signals ...
void GetSignals(
XSignal &result[], // Holds Result ...
ENUM_X_SIGNAL_TYPE type // Specified Sginal Type ...
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(signals);
//
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
// Loop ...
for (int i = signalsCount - 1; i >= 0; i--)
{
//
XSignal iSignal = signals[i];
//
if (type == X_SIGNAL_UNKNOWN)
{
Add(
iSignal,
result);
}
else if (iSignal.type == type)
{
Add(
iSignal,
result);
}
}
}
//
// Filter Signals By Searching Comments ...
void FilterSignals(
XSignal &result[], // Holds Result ...
const string query, // Search in Comment Qeury ...
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specified Sginal Type ...
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
//
// Validate Args ...
if (
StringLen(query) <= 0 ||
signalsCount <= 0)
{
return;
}
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
int queryPos = StringFind(
iSignal.comment,
query);
bool isContains = queryPos > -1;
if (!isContains)
{
continue;
}
//
Add(
iSignal,
result);
}
}
//
// Get All Trades Which Candle Passed after Open ...
void GetOldSignals(
XSignal &result[], // Holds Result
int life, // Max Candle Passed after Trades Open
ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
// Normalize Period ...
if (period == NULL)
{
period = _Period;
}
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
// Current Time Frame Candle Index ...
int currentBarIndex = 0;
//
// Loop through Positions ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
// Retrieve Trade Open Bar Index based on Current Period ...
int tradeOpenBarIndex = iBarShift(
mSymbol,
period,
iSignal.time);
//
// Calculate Trade Life ...
int diff = MathAbs(currentBarIndex - tradeOpenBarIndex);
//
bool isPassed = diff >= life;
if (isPassed)
{
//
Add(
iSignal,
result);
}
}
}
//
// Get In Profit Signals ...
void GetInProfitSignals(
XSignal &result[], // Holds Result
double minProfit = 0, // Minimum Profit To Close Trades
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
bool isPassed = minProfit <= 0 && iSignal.profit > 0
? true
: iSignal.profit >= minProfit;
if (isPassed)
{
Add(
iSignal,
result);
}
}
}
//
// Get In Drawdown Signals ...
void GetInDrawdownSignals(
XSignal &result[], // Holds Result
double maxDrawDown = 0, // Minimum Profit To Close Trades
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
bool isPassed = maxDrawDown <= 0 && iSignal.profit < 0
? true
: iSignal.profit >= (-1 * maxDrawDown);
if (isPassed)
{
Add(
iSignal,
result);
}
}
}
//
// Retrieve Max In Draw Down Trade ...
XSignal GetMaxInDrawdownSignal(
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
XSignal result = {};
//
XSignal signals[];
GetInDrawdownSignals(
signals,
0,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
result =
(result.ticket <= 0 &&
result.profit == 0) ||
result.profit > iSignal.profit
? iSignal
: result;
}
//
return result;
}
//
// Calculate Profits Of all Open Signals ...
double GetSignalsProfit(
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
double result = 0;
//
XSignal signals[];
GetSignals(signals, type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
result += iSignal.profit;
}
//
return result;
}
//
// END Retrieve ...
//
//
// START Signal Execution Actions ...
//
//
// Execute a Signal in Market ...
ENUM_EXECUTION_SIGNAL_RESULT ExecuteSignal(
XSignal &signal, // Specified Signal
bool ignoreTPSL = false, // Ignore Signal TP and SL for Virtal Handling
bool ignoreNumberOfTraes = false, // Ignore Number of Trades
bool checkAccountConditions = true // Check Account Balance, Equity and Free Margin for Signal Execution
)
{
//
ENUM_EXECUTION_SIGNAL_RESULT result = X_TRADER_UNKNOWN_ERROR;
//
// Validate Signal ...
bool isValid = IsValidSignal(signal);
if (!isValid)
{
//
result = X_TRADER_INVALID_SIGNAL_ERROR;
return result;
}
//
// Check Account Equity ...
bool isEquityPassed = !checkAccountConditions
? true
: IsEquityReadyForTrade();
if (!isEquityPassed)
{
//
result = X_TRADER_NOT_ENOUGH_EQUITY_ERROR;
return result;
}
//
// Check Account Balance ...
bool isBalancePassed = !checkAccountConditions
? true
: IsBalanceReadyForTrade();
if (!isBalancePassed)
{
//
result = X_TRADER_NOT_ENOUGH_BALANCE_ERROR;
return result;
}
//
// Check Account FreeMargin ...
bool isFreeMarginPassed = !checkAccountConditions
? true
: IsFreeMarginReadyForTrade();
if (!isFreeMarginPassed)
{
//
result = X_TRADER_NOT_ENOUGH_MARIGIN_ERROR;
return result;
}
//
// Check Number of Open Trades ...
int openTradesCount = Count();
bool isTradeCountPassed = ignoreNumberOfTraes
? true
: openTradesCount < mMaxAllowedTrades;
if (!isTradeCountPassed)
{
//
result = X_TRADER_MAX_TRADES_REACHED_ERROR;
return result;
}
//
bool isExecuted =
signal.type == X_SIGNAL_LONG
? Buy(
signal.volume,
signal.entry,
ignoreTPSL
? 0
: signal.sl,
ignoreTPSL
? 0
: signal.tp,
signal.comment)
: signal.type == X_SIGNAL_SHORT
? Sell(
signal.volume,
signal.entry,
ignoreTPSL
? 0
: signal.sl,
ignoreTPSL
? 0
: signal.tp,
signal.comment)
: false;
if (isExecuted)
{
//
ulong ticket = PositionGetTicket(PositionsTotal() - 1);
//
signal.id = ticket;
signal.ticket = ticket;
//
AddOrUpdateSignalInfo(signal);
//
result = X_TRADER_SUCCEED_EXECUTION;
}
//
return result;
}
//
// This Function, Handling Following Works on Open Positions:
// - Close On SL if Reached ...
// - Close On TP if Reached ...
// - Make Risk Free Trades ...
void HandleSignals(
XTraderHandlerResult &result, // Holds Result
bool ignoreTPSL = true, // Ignore Signal TP and SL for Virtal Handling
bool ignoreRiskFree = false // Ignore Risk Free Trdaes
)
{
//
// Cleanup Result ...
CleanBuffer(result.sl);
CleanBuffer(result.tp);
CleanBuffer(result.rf);
//
// Reading Open Positions ...
XSignal signals[];
GetSignals(signals);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
double deviation = mSlippage * GetPoints(mSymbol);
//
// Loop ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
bool isLong = iSignal.type == X_SIGNAL_LONG;
double entry = GetEntry(iSignal.symbol, iSignal.type);
double exit = GetExit(iSignal.symbol, iSignal.type);
double appliedTPPrice =
iSignal.tp > 0
? isLong
? iSignal.tp - deviation
: iSignal.tp + deviation
: 0;
double appliedSLPrice =
iSignal.sl > 0
? isLong
? iSignal.sl + deviation
: iSignal.sl - deviation
: 0;
//
// Handle SL ...
if (
//
!ignoreTPSL
//
&&
//
iSignal.sl > 0
//
&&
//
exit <= appliedSLPrice
//
)
{
//
string comment = GenerateSignalSLComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result.sl);
}
}
//
// Handle TP ...
if (
//
!ignoreTPSL
//
&&
//
iSignal.tp > 0
//
&&
//
exit >= appliedTPPrice
//
)
{
//
string comment = GenerateSignalTPComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result.tp);
}
}
//
// Handle Risk Free ...
if (
//
!ignoreRiskFree
//
&&
//
iSignal.riskFreeStep > 0
//
&&
//
iSignal.riskFreeRate > 0
//
)
{
//
// Base Price is ENTRY, then Last Level, in each level SL is Last Level ...
int level = 1;
double stepPrice = PipsToPrice(iSignal.riskFreeStep);
double basePrice =
isLong
? iSignal.sl != 0 && iSignal.sl > iSignal.entry ? iSignal.sl : iSignal.entry
: iSignal.sl != 0 && iSignal.sl < iSignal.entry ? iSignal.sl
: iSignal.entry;
double priceLevel = MathAbs(exit - basePrice) / stepPrice;
//
if (priceLevel > 1)
{
//
while (priceLevel > level && priceLevel > level + 1)
{
level++;
}
//
double baseRiskFreeLevelExitPrice = (level * stepPrice);
double riskFreeLevelExitPrice =
isLong
? (basePrice + baseRiskFreeLevelExitPrice) - deviation
: (basePrice - baseRiskFreeLevelExitPrice) + deviation;
//
bool canRiskFree =
isLong
? exit >= riskFreeLevelExitPrice
: exit <= riskFreeLevelExitPrice;
//
if (canRiskFree)
{
//
double volume = iSignal.volume;
double riskFreeRate = iSignal.riskFreeRate;
double riskFreeVolume = riskFreeRate * volume;
riskFreeVolume = NormalizeVolume(riskFreeVolume);
//
double entry = GetEntry(
iSignal.symbol,
iSignal.type);
double exit = GetExit(
iSignal.symbol,
iSignal.type);
double spread = GetSpread(iSignal.symbol);
long stopLevels = SymbolInfoInteger(
iSignal.symbol,
SYMBOL_TRADE_STOPS_LEVEL) +
SymbolInfoInteger(iSignal.symbol, SYMBOL_SPREAD);
double slDistance = spread * 2;
//
double sl =
isLong
? iSignal.tp - slDistance
: iSignal.tp + slDistance;
sl = NormalizePrice(sl, iSignal.symbol);
//
double tp =
isLong
? iSignal.tp + stepPrice
: iSignal.tp - stepPrice;
tp = NormalizePrice(tp, iSignal.symbol);
//
string comment = GenerateSignalRFComment(iSignal, (int)level);
//
ResetLastError();
//
bool isClosedPartial = ClosePartial(
iSignal.ticket,
riskFreeVolume,
comment);
//
if (isClosedPartial)
{
// //
// bool isModified = Modify(
// iSignal.ticket,
// 0,
// tp);
//
// if (isModified)
// {
//
Add(
iSignal,
result.rf);
//
AddOrUpdateSignalInfo(iSignal);
// }
}
}
}
}
}
}
//
// Close All Trades ...
void CloseSignals(
XSignal &result[], // Holds Result
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
string comment = GenerateSignalForceCloseComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result);
}
}
}
//
// Close Pyramid Signals ...
void CloseInPyramidSignals(
XSignal &result[], // Holds Result
double pyramid = 0, // Close Pyramid Profit
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetSignals(
signals,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
double profit = 0;
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
profit += iSignal.profit;
}
//
// Normalize Pyramid ...
if (pyramid < 0)
{
pyramid = 0;
}
//
if (profit > pyramid)
{
CloseSignals(result);
}
}
//
// Close All Trades Which Candle Passed after Open ...
void CloseOldSignals(
XSignal &result[], // Holds Result
int life, // Max Candle Passed after Trades Open
ENUM_TIMEFRAMES period = NULL, // Calculate Candles based on time frame
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetOldSignals(
signals,
life,
period,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
string comment = GenerateSignalAgeComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result);
}
}
}
//
// Close In Profit Signals ...
void CloseInProfitSignals(
XSignal &result[], // Holds Result
double minProfit = 0, // Minimum Profit To Close Trades
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetInProfitSignals(
signals,
minProfit,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
string comment = GenerateSignalProfitComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result);
}
}
}
//
// Close In Drawdown Signals ...
void CloseInDrawdownSignals(
XSignal &result[], // Holds Result
double maxDrawDown = 0, // Minimum Profit To Close Trades
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Specify Type of Positions
)
{
//
CleanBuffer(result);
//
XSignal signals[];
GetInDrawdownSignals(
signals,
maxDrawDown,
type);
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
string comment = GenerateSignalProfitComment(iSignal);
//
bool isClosed = Close(
iSignal.ticket,
comment);
if (isClosed)
{
Add(
iSignal,
result);
}
}
}
//
// END Signal Execution Actions ...
//
//
// START Actions ...
//
//
// Force Open a Buy/Long Position ...
bool Buy(
double volume, // position volume
double price, // execution price
double sl = 0, // stop loss price
double tp = 0, // take profit price
const string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.Buy(
volume,
mSymbol,
price,
sl,
tp,
comment);
//
return result;
}
//
// Send BUY LIMIT order ...
bool BuyLimit(
double volume, // order volume
double price, // order price
double sl = 0.0, // stop loss price
double tp = 0.0, // take profit price
ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime
datetime expiration = 0, // order expiration time
string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.BuyLimit(
volume,
price,
mSymbol,
sl,
tp,
typeTime,
expiration,
comment);
//
return result;
}
//
// Send BUY STOP order ...
bool BuyStop(
double volume, // order volume
double price, // order price
double sl = 0.0, // stop loss price
double tp = 0.0, // take profit price
ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime
datetime expiration = 0, // order expiration time
string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.BuyStop(
volume,
price,
mSymbol,
sl,
tp,
typeTime,
expiration,
comment);
//
return result;
}
//
// Force Open a Sell/Short Position ...
bool Sell(
double volume, // position volume
double price, // execution price
double sl = 0, // stop loss price
double tp = 0, // take profit price
const string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.Sell(
volume,
mSymbol,
price,
sl,
tp,
comment);
//
return result;
}
//
// Send SELL LIMIT order ...
bool SellLimit(
double volume, // order volume
double price, // order price
double sl = 0.0, // stop loss price
double tp = 0.0, // take profit price
ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime
datetime expiration = 0, // order expiration time
string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.SellLimit(
volume,
price,
mSymbol,
sl,
tp,
typeTime,
expiration,
comment);
//
return result;
}
//
// Send SELL STOP order ...
bool SellStop(
double volume, // order volume
double price, // order price
double sl = 0.0, // stop loss price
double tp = 0.0, // take profit price
ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime
datetime expiration = 0, // order expiration time
string comment = "" // comment
)
{
//
bool result = false;
//
result = mTrader.SellStop(
volume,
price,
mSymbol,
sl,
tp,
typeTime,
expiration,
comment);
//
return result;
}
//
// Modify Position ...
bool Modify(
const ulong ticket, // position ticket
double sl = 0, // stop loss price
double tp = 0, // take profit
const string comment = "" // comment
)
{
//
bool result = false;
//
// Validate Args ...
if (tp <= 0 && sl <= 0)
{
result = false;
return result;
}
//
result = mTrader.PositionModify(
ticket,
sl,
tp,
comment);
//
return result;
}
//
// Close Position By Ticket ...
bool Close(
ulong ticket, // Position Ticket
string comment = "" // Close Position By Specific Comment
)
{
//
bool result = false;
//
// Try to Select Position ...
if (!mPositionInfo.SelectByTicket(ticket))
{
return result;
}
//
// Close Position By Specific Comment ...
result = mTrader.PositionClose(
ticket,
mSlippage,
comment);
if (result)
{
RemoveSignal(ticket);
}
//
return result;
}
//
// Close Partial By Ticket ...
bool ClosePartial(
ulong ticket, // Position Ticket
double volume, // Volume Size for Partial Closing
string comment = "" // Close Position By Specific Comment
)
{
//
bool result = false;
//
if (!mPositionInfo.SelectByTicket(ticket))
{
return result;
}
//
result = mTrader.PositionClosePartial(
ticket,
volume,
mSlippage,
comment);
//
return result;
}
//
// END Actions ...
//
//
// START Account Related ...
//
//
// Check Account Has Minimum Balance For Trade ...
bool IsBalanceReadyForTrade()
{
//
bool result = false;
//
result = mAccountInfo.GetBalance() >= mMinBallanceForOpenTrades;
//
return result;
}
//
// Check Free Margin Has Enough For Trade ...
bool IsFreeMarginReadyForTrade()
{
//
bool result = false;
//
double freeMargin = mAccountInfo.GetFreeMargin();
//
result = freeMargin >= mMinAllowedFreeMarginForOpenTrades;
//
return result;
}
//
// Check Equity Has Enough For Trade ...
bool IsEquityReadyForTrade()
{
//
bool result = false;
//
double equity = mAccountInfo.GetEquity();
//
result = equity >= mMinAllowedFreeMarginForOpenTrades;
//
return result;
}
//
// END Account Related ...
//
//
// START Signal Related ...
//
//
// Validate Signal ...
bool IsValidSignal(
XSignal &signal // Specified Signal for Execution
)
{
//
bool result = false;
//
// Validate Signal Type ...
result = signal.type != X_SIGNAL_UNKNOWN;
if (!result)
{
return result;
}
//
// Check Symbol ...
result = StringLen(signal.symbol) == 0 ? true : signal.symbol == mSymbol;
if (!result)
{
return result;
}
//
// Check magic number ...
result = signal.magicNumber <= 0 ? true : signal.magicNumber == mMagicNumber;
if (!result)
{
return result;
}
//
// Check Entry ...
result = signal.entry > 0;
if (!result)
{
return result;
}
//
// Check SL ...
result = signal.sl == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.sl < signal.entry
: signal.sl > signal.entry;
if (!result)
{
return result;
}
//
// Check TP ...
result = signal.tp == 0 ? true : signal.type == X_SIGNAL_LONG ? signal.tp > signal.entry
: signal.tp < signal.entry;
if (!result)
{
return result;
}
//
// Check Volume ...
result = signal.volume > 0;
if (!result)
{
return result;
}
//
// Check Time ...
result = signal.time > 0;
if (!result)
{
return result;
}
//
return result;
}
//
// Get Signal InDirection (Reversal) Type ...
ENUM_X_SIGNAL_TYPE GetSignalIndirectionType(
XSignal &signal // Specified Signal
)
{
//
ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN;
//
switch (signal.type)
{
//
case X_SIGNAL_LONG:
result = X_SIGNAL_SHORT;
break;
//
case X_SIGNAL_SHORT:
result = X_SIGNAL_LONG;
break;
}
//
return result;
}
//
// Calculate SignalAge ...
int GetSignalAge(
datetime time // Signal Execution Time
)
{
//
int result = 0;
//
// Validate Arg ...
if (time <= 0)
{
return result;
}
//
int sIndex = iBarShift(
mSymbol,
_Period,
time);
//
datetime cTime = iTime(
mSymbol,
_Period,
0);
int cIndex = iBarShift(
mSymbol,
_Period,
cTime);
//
result = MathAbs(cIndex - sIndex);
//
return result;
}
int GetSignalAge(
datetime time, // Signal Execution Time
ENUM_TIMEFRAMES period // Specify Time Frame
)
{
//
int result = 0;
//
// Validate Arg ...
if (time <= 0)
{
return result;
}
//
int sIndex = iBarShift(
mSymbol,
period,
time);
//
datetime cTime = iTime(
mSymbol,
period,
0);
int cIndex = iBarShift(
mSymbol,
_Period,
cTime);
//
result = MathAbs(cIndex - sIndex);
//
return result;
}
int GetSignalAge(
XSignal &signal // Specified Signal
)
{
//
int result = 0;
//
// Validate Arg ...
if (
signal.time <= 0 ||
!IsValid(signal, mMagicNumber))
{
return result;
}
//
result = GetSignalAge(signal.time);
//
return result;
}
int GetSignalAge(
XSignal &signal, // Specify Signal
ENUM_TIMEFRAMES period // Specify Time Frame
)
{
//
int result = 0;
//
// Validate Arg ...
if (
signal.time <= 0 ||
!IsValid(signal, mMagicNumber))
{
return result;
}
//
result = GetSignalAge(
signal.time,
period);
//
return result;
}
//
// Prepare a Signall ...
XSignal GenerateSignal(
ENUM_X_SIGNAL_TYPE type, // Signal Type
double tp = 0, // Take Profit
double sl = 0, // Stop Loss
double volume = 0, // Volume
double riskFreeStep = 0, // Risk Free Step Price
double riskFreeRate = 0 // Risk Free Rate
)
{
//
XSignal result = {};
//
// Validate Arg ...
if (type == X_SIGNAL_UNKNOWN)
{
return result;
}
//
// Check Signal Type ...
bool isLong = type == X_SIGNAL_LONG;
//
// Retrieve entry Price ...
double entry = GetEntry(mSymbol, type);
double spread = GetSpread(mSymbol);
//
result.tp = tp;
result.sl = sl;
result.type = type;
result.entry = entry;
result.symbol = mSymbol;
result.magicNumber = mMagicNumber;
result.riskFreeStep = riskFreeStep;
result.riskFreeRate = riskFreeRate;
result.time = iTime(mSymbol, _Period, 0);
result.volume = NormalizeVolume(volume, mSymbol);
//
// Since we Use signal instance to Generate Comment, this must be at the end ...
result.comment = GenerateSignalComment(result);
//
return result;
}
//
// Generate Comments for Specific Signal ...
string GenerateSignalComment(
ENUM_X_SIGNAL_TYPE type, // Specify Kind Signal Type
double volume, // Signal Volume
bool isCrossSignal = false // Specify Signal Cross
)
{
//
string result = "";
//
string typeStr = GetSignalType(type);
if (
volume <= 0 ||
StringLen(typeStr) == 0)
{
return result;
}
//
volume = NormalizeVolume(volume, mSymbol);
//
result = mTag + (!isCrossSignal ? "" : "_Cross_") + "_" + typeStr;
//
return result;
}
string GenerateSignalComment(
XSignal &signal, // Specified Signal
bool isCrossSignal = false // Specify Signal Cross
)
{
//
string result = GenerateSignalComment(
signal.type,
signal.volume,
isCrossSignal
//
);
//
return result;
}
//
// Generate Signal RF TP Comment ...
string GenerateSignalRFComment(
XSignal &signal, // Specified Signal
int level // Which Step of RFS
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
double exit = GetExit(signal.symbol, signal.type);
//
result =
//
X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.ticket + ")_" + (string)level + ": " + string(exit);
//
;
//
return result;
}
//
// Generate Signal TP Comment ...
string GenerateSignalTPComment(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
double exit = GetExit(signal.symbol, signal.type);
//
result =
//
X_SIGNAL_TP + "(" + (string)signal.ticket + "): " + string(exit);
//
;
//
return result;
}
//
// Generate Signal SL Comment ...
string GenerateSignalSLComment(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
double exit = GetExit(signal.symbol, signal.type);
//
result =
//
X_SIGNAL_SL + "(" + (string)signal.ticket + "): " + string(exit);
//
;
//
return result;
}
//
// Generate Signal Profit Comment ...
string GenerateSignalProfitComment(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
result =
//
"Profit(" + (string)signal.ticket + "): " + string(signal.profit);
//
;
//
return result;
}
//
// Generate Signal Force Close Comment ...
string GenerateSignalForceCloseComment(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
result =
//
"FC(" + (string)signal.ticket + "): " + string(signal.profit);
//
;
//
return result;
}
//
// Generate Signal Age Comment ...
string GenerateSignalAgeComment(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Signal and it's Ticket ...
if (!IsValidSignal(signal) || signal.ticket <= 0)
{
return result;
}
//
int age = GetSignalAge(signal);
//
result =
//
"(" + (string)signal.ticket + ") A: " + (string)age + ", P:" + string(signal.profit);
//
;
//
return result;
}
//
// Generate a Signal Object name for Draw Events On Chart ...
string GenerateSignalObjectName(
ulong ticket // Specify Ticket
)
{
//
string result = "";
//
// Validate Arg ...
if (ticket <= 0)
{
return result;
}
//
// TICKET ...
// it is very importants since they hold position info ...
result += "T(" + (string)ticket + ")";
//
return result;
}
string GenerateSignalObjectName(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
// Validate Arg ...
if (!IsValid(signal, mMagicNumber))
{
return result;
}
//
result = GenerateSignalObjectName(signal.ticket);
//
return result;
}
//
// Genrate a Signal Event Object Name ...
string GenerateSignalEventObjectName(
ulong ticket // Specify Ticket
)
{
//
string result = "";
//
result = GenerateSignalObjectName(ticket) + "_Event";
//
return result;
}
string GenerateSignalEventObjectName(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
result = GenerateSignalEventObjectName(signal.ticket);
//
return result;
}
//
// Convert a Signal to String Representation ...
string ToString(
XSignal &signal // Specified Signal
)
{
//
string result = "";
//
if (!IsValid(signal, mMagicNumber) || signal.ticket <= 0)
{
return result;
}
//
// TICKET ...
// it is very importants since they hold position info ...
result += X_SIGNAL_TICKET + "(" + (string)signal.ticket + ")";
//
// TYPE ...
string typeStr = GetSignalType(signal.type);
result += "_" + X_SIGNAL_TYPE + "(" + typeStr + ")";
//
// TP ...
result += "_" + X_SIGNAL_TP + "(" + (string)signal.tp + ")";
//
// SL ...
result += "_" + X_SIGNAL_SL + "(" + (string)signal.sl + ")";
//
// RFS ...
result += "_" + X_SIGNAL_RISKFREE_STEP + "(" + (string)signal.riskFreeStep + ")";
//
// RFR ...
result += "_" + X_SIGNAL_RISKFREE_RATE + "(" + (string)signal.riskFreeRate + ")";
//
return result;
}
//
// Convert an string to signal ...
XSignal FromString(
string represent // String Represenation of a Signal
)
{
//
XSignal result = {};
//
// Validate Arg ...
if (StringLen(represent) == 0)
{
return result;
}
//
// TICKET ...
string ticketStr = ExtractString(
represent,
X_SIGNAL_TICKET + "(",
")");
if (StringLen(ticketStr) > 0)
{
result.ticket = (ulong)ticketStr;
}
//
// TYPE ...
string typeStr = ExtractString(
represent,
"_" + X_SIGNAL_TYPE + "(",
")");
if (StringLen(typeStr) > 0)
{
//
ENUM_X_SIGNAL_TYPE type = GetSignalType(typeStr);
result.type = type;
}
//
// TP ...
string tpStr = ExtractString(
represent,
"_" + X_SIGNAL_TP + "(",
")");
if (StringLen(tpStr) > 0)
{
//
double tp = (double)tpStr;
result.tp = tp;
}
//
// SL ...
string slStr = ExtractString(
represent,
"_" + X_SIGNAL_SL + "(",
")");
if (StringLen(slStr) > 0)
{
//
double sl = (double)slStr;
result.sl = sl;
}
//
// RFS ...
string rfsStr = ExtractString(
represent,
"_" + X_SIGNAL_RISKFREE_STEP + "(",
")");
if (StringLen(rfsStr) > 0)
{
//
double rfs = (double)rfsStr;
result.riskFreeStep = rfs;
}
//
// RFR ...
string rfrStr = ExtractString(
represent,
"_" + X_SIGNAL_RISKFREE_RATE + "(",
")");
if (StringLen(rfrStr) > 0)
{
//
double rfr = (double)rfrStr;
result.riskFreeRate = rfr;
}
//
return result;
}
void FromString(
XSignal &result, // Holds Result
string represent // String Represenation of a Signal
)
{
//
// Validate Arg ...
if (StringLen(represent) == 0)
{
return;
}
//
XSignal fs = FromString(represent);
//
// Fillisg Result by Retrieved Values ...
result.tp = fs.tp;
result.sl = fs.sl;
result.type = fs.type;
result.ticket = fs.ticket;
result.riskFreeStep = fs.riskFreeStep;
result.riskFreeRate = fs.riskFreeRate;
}
//
// END Signal Related ...
//
//
// START Deals ...
//
//
// Count Deals ...
int DealsCount(
datetime start = -1, // Start Date
datetime end = -1 // End Date
)
{
//
int result = 0;
//
XDeal deals[];
GetDeals(
deals,
start,
end);
result = ArraySize(deals);
//
return result;
}
//
// Retrieve All Deals ...
void GetDeals(
XDeal &result[], // Hold's Result
datetime start = -1, // Start Date
datetime end = -1 // End Date
)
{
//
CleanBuffer(result);
//
// Select History if Start and End date provided ...
if (start > -1)
{
//
// Normalize End date ...
if (end == -1)
{
end = TimeCurrent();
}
//
bool isSelect = HistorySelect(start, end);
if (!isSelect)
{
return;
}
}
//
int total = HistoryDealsTotal();
if (total <= 0)
{
return;
}
//
// Loop ...
for (int i = total - 1; i >= 0; i--)
{
//
// Select by Index ...
bool isSelect = mDealInfo.SelectByIndex(i);
if (!isSelect)
{
continue;
}
//
// Check Magic ...
ulong magic = mDealInfo.Magic();
bool isMagicSame = magic == mMagicNumber;
if (!isMagicSame)
{
continue;
}
//
// Check Symbol ...
string symbol = mDealInfo.Symbol();
bool isSymbolSame = symbol == mSymbol;
if (!isSymbolSame)
{
continue;
}
//
XDeal deal = ToXDealByIndex(i);
//
Add(
deal,
result);
}
}
//
// Retrieve Last Deal ...
XDeal GetLastDeal()
{
//
XDeal result = {};
//
XDeal deals[];
GetDeals(deals);
int dealsCount = ArraySize(deals);
if (dealsCount <= 0)
{
return result;
}
//
result = deals[0];
//
return result;
}
//
// END Deals ...
//
//
// START Orders ...
//
//
// Count Orders ...
int OrdersCount(
datetime start = -1, // Start Date
datetime end = -1 // End Date
)
{
//
int result = 0;
//
XOrder orders[];
GetOrders(
orders,
start,
end);
result = ArraySize(orders);
//
return result;
}
//
// Retrieve Orders ...
void GetOrders(
XOrder &result[], // Hold's Result
datetime start = -1, // Start Date
datetime end = -1 // End Date
)
{
//
CleanBuffer(result);
//
// Select History if Start and End date provided ...
if (start > -1)
{
//
// Normalize End date ...
if (end == -1)
{
end = TimeCurrent();
}
//
bool isSelect = HistorySelect(start, end);
if (!isSelect)
{
return;
}
}
//
int total = HistoryOrdersTotal();
if (total <= 0)
{
return;
}
//
// Loop ...
for (int i = total - 1; i >= 0; i--)
{
//
// Select by Index ...
bool isSelect = mOrderInfo.SelectByIndex(i);
if (!isSelect)
{
continue;
}
//
// Check Magic ...
ulong magic = mOrderInfo.Magic();
bool isMagicSame = magic == mMagicNumber;
if (!isMagicSame)
{
continue;
}
//
// Check Symbol ...
string symbol = mOrderInfo.Symbol();
bool isSymbolSame = symbol == mSymbol;
if (!isSymbolSame)
{
continue;
}
//
XOrder order = ToXOrderByIndex(i);
//
Add(
order,
result);
}
}
//
// Retrieve Last Order ...
XOrder GetLastOrder()
{
//
XOrder result = {};
//
XOrder orders[];
GetOrders(orders);
int ordersCount = ArraySize(orders);
if (ordersCount <= 0)
{
return result;
}
//
result = orders[0];
//
return result;
}
//
// END Orders ...
//
//
// all protected features ...
protected:
//
// all private features ...
private:
//
// Specified Unique Tag ...
string mTag;
//
// which Symbol ...
string mSymbol;
//
// using deviation, it must be in Point ...
int mSlippage;
//
// using magic number ...
ulong mMagicNumber;
//
// Specify Max Allowed Trades
int mMaxAllowedTrades;
//
// Minimum Free Marging for Open Trades
double mMinAllowedFreeMarginForOpenTrades;
//
// Minimum Balance for Open Trades
double mMinBallanceForOpenTrades;
//
// using CTrade instance ...
XSCTrade mTrader;
//
// Deals Info ...
CDealInfo mDealInfo;
//
// Order Info ...
COrderInfo mOrderInfo;
//
// An Instance Of XCAccount Info for Handling Account Related Actions ...
XCAccountInfo mAccountInfo;
//
// using PositionInfo instance ...
CPositionInfo mPositionInfo;
//
// Signal Manager ...
XCSignalManager mSignalManager;
//
// START Signal Private ...
//
//
// Add Or Update Signal ...
void AddOrUpdateSignalInfo(
XSignal &signal // Specified Signal
)
{
// //
// bool isExists = mSignalManager.IsExists(signal);
// if (!isExists)
// {
// //
// color longColor = clrAqua;
// color shortColor = clrFuchsia;
// //
// DrawSignalShape(
// signal,
// longColor,
// shortColor);
// }
// //
// bool isAddOrUpdated = mSignalManager.AddOrUpdate(signal);
//
string name = GenerateSignalEventObjectName(signal);
//
bool isExists = IsDrawExists(name);
if (isExists)
{
RemoveSignal(signal.ticket);
}
//
DrawSignalEvent(signal);
}
//
// Retrieve Signal String From Chart Event ...
string RetrieveSignalContent(
ulong ticket, // Specify Position Ticket
int chartId = -1, // Specify Chart ID
int subWindow = -1 // Specify SubWindow ID
)
{
//
string result = "";
//
// Normalize Chart and SubWindow ID ...
if (chartId == -1)
{
chartId = 0;
}
if (subWindow == -1)
{
subWindow = 0;
}
//
// Validate Args ...
if (ticket <= 0)
{
return result;
}
//
// Get Signal Event Name ...
string sObjName = GenerateSignalEventObjectName(ticket);
if (StringLen(sObjName) == 0)
{
return result;
}
//
// Check Signal Event Exists ...
bool isExists = IsDrawExists(sObjName);
if (!isExists)
{
return result;
}
//
// Loop Through Objects ...
int count = ObjectsTotal(
chartId,
subWindow);
for (int i = count - 1; i >= 0; i--)
{
//
// Retrieve Object Name ...
string objectName = ObjectName(chartId, i, subWindow);
//
// Find Signal Ticket Position in Object Name ...
int stPos = StringFind(
objectName,
sObjName);
if (stPos < 0)
{
continue;
}
//
// Retrieve Object Type and Check it Event ...
int oType = (int)ObjectGetInteger(chartId, objectName, OBJPROP_TYPE);
if (oType != OBJ_EVENT)
{
continue;
}
//
// Retrieve Object Text as String Representation OF Signal ...
result = ObjectGetString(chartId, objectName, OBJPROP_TEXT);
break;
}
//
return result;
}
XSignal RetrieveSignal(
ulong ticket // Specify Position Ticket
)
{
//
XSignal result = {};
//
if (ticket <= 0)
{
return result;
}
//
string signalContent = RetrieveSignalContent(ticket);
result = FromString(
signalContent);
//
// result = mSignalManager.Get(ticket);
//
return result;
}
void RetrieveSignal(
XSignal &signal // Specified Signal
)
{
// //
// XSignal tSignal = mSignalManager.Get(signal.ticket);
// //
// // Fill signal by tSignal Data ...
// // since tese properties may change in signal manipulation times ...
// signal.tp = tSignal.tp;
// signal.sl = tSignal.sl;
// signal.riskFreeStep = tSignal.riskFreeStep;
// signal.riskFreeRate = tSignal.riskFreeRate;
//
string signalContent = RetrieveSignalContent(signal.ticket);
//
FromString(
signal,
signalContent);
}
//
// Draw a Signal on Screen ...
void DrawSignalEvent(
XSignal &signal, // Specify Draw which Signal on Screen
color longColor = clrAqua, // Long Signal Object Color
color shortColor = clrFuchsia, // Short Signal Object Color
int chartId = -1, // Specify Chart ID
int subWindow = -1 // Specify SubWindow ID
)
{
//
// Validate Args ...
if (
signal.ticket <= 0 ||
!IsValid(signal, mMagicNumber) ||
signal.type == X_SIGNAL_UNKNOWN)
{
return;
}
//
// Normalize Chart and SubWindow ID ...
if (chartId == -1)
{
chartId = 0;
}
if (subWindow == -1)
{
subWindow = 0;
}
//
bool isLong = signal.type == X_SIGNAL_LONG;
//
// Simply Draw an Arrow on Chart for Representing Signal Info ...
string name = GenerateSignalEventObjectName(signal);
string content = ToString(signal);
if (StringLen(content) == 0)
{
return;
}
//
color signalColor = isLong ? longColor : shortColor;
//
// Create an Event On Chart ...
bool isCreated = EventCreate(
chartId,
name,
subWindow,
content,
signal.time,
signalColor);
if (isCreated)
{
//
DrawSignalShape(
signal,
longColor,
shortColor);
}
}
//
// Remove Signal Object from Chart ...
bool RemoveSignal(
ulong ticket, // Specify Position Ticket
int chartId = -1 // Specify Chart ID
)
{
//
bool result = false;
//
// Validate Arg ...
if (ticket <= 0)
{
return result;
}
//
// Normalize Chart Id ...
if (chartId <= 0)
{
chartId = 0;
}
//
// Generate Signal Object Name ...
string signalObjectName = GenerateSignalEventObjectName(ticket);
//
// Remove Object from Chart ...
result = RemoveDraw(signalObjectName);
//
return result;
}
bool RemoveSignal(
XSignal &signal, // Specify Signal
int chartId = -1 // Specify Chart ID
)
{
//
bool result = false;
//
result = RemoveSignal(
signal.ticket,
chartId);
//
return result;
}
//
// Converts a Position to Signal ...
//
// Convert Position to Signal by Index ...
XSignal PositionToSignal(int index)
{
//
XSignal result = {};
//
if (!mPositionInfo.SelectByIndex(index))
{
return result;
}
//
ulong ticket = mPositionInfo.Ticket();
result = PositionToSignal(ticket);
//
return result;
}
//
// Position To Signal by Ticket ...
XSignal PositionToSignal(ulong ticket)
{
//
XSignal result = {};
//
if (!mPositionInfo.SelectByTicket(ticket))
{
return result;
}
//
string signalContent = RetrieveSignalContent(ticket);
if (StringLen(signalContent) > 0)
{
//
// Fill Additional Contents ...
FromString(
result,
signalContent);
}
//
// Ticket ...
result.ticket = mPositionInfo.Ticket();
//
// ID ...
result.id = mPositionInfo.Identifier();
//
// Symbol ...
result.symbol = mPositionInfo.Symbol();
//
// Type ...
ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)mPositionInfo.PositionType();
ENUM_X_SIGNAL_TYPE type = pType == POSITION_TYPE_BUY ? X_SIGNAL_LONG : X_SIGNAL_SHORT;
result.type = type;
//
// MagicNumber ...
result.magicNumber = mPositionInfo.Magic();
//
// Entry/Open Price ...
result.entry = mPositionInfo.PriceOpen();
//
// Take Profit ...
result.tp = result.tp <= 0 && mPositionInfo.TakeProfit() > 0
? mPositionInfo.TakeProfit()
: result.tp;
//
// Stop Loss ...
result.sl = result.sl <= 0 && mPositionInfo.StopLoss() > 0
? mPositionInfo.StopLoss()
: result.sl;
//
// Profit ...
result.profit = mPositionInfo.Profit();
//
// Time ...
result.time = mPositionInfo.Time();
//
// Volume ...
result.volume = mPositionInfo.Volume();
//
// Comment ...
result.comment = mPositionInfo.Comment();
//
return result;
}
//
// Converts a Deal to XDeal by Index ...
XDeal ToXDealByIndex(int index)
{
//
XDeal result = {};
//
bool isSelect = mDealInfo.SelectByIndex(index);
if (!isSelect)
{
return result;
}
//
// Read Deal Ticket ...
ulong ticket = mDealInfo.Ticket();
result = ToXDealByTicket(ticket);
//
return result;
}
//
// Converts a Deal to XDeal by Ticket ...
XDeal ToXDealByTicket(ulong ticket)
{
//
XDeal result = {};
//
mDealInfo.Ticket(ticket);
//
result.time = mDealInfo.Time();
result.swap = mDealInfo.Swap();
result.magic = mDealInfo.Magic();
result.order = mDealInfo.Order();
result.entry = mDealInfo.Entry();
result.price = mDealInfo.Price();
result.ticket = mDealInfo.Ticket();
result.symbol = mDealInfo.Symbol();
result.type = mDealInfo.DealType();
result.profit = mDealInfo.Profit();
result.volume = mDealInfo.Volume();
result.comment = mDealInfo.Comment();
result.positionId = mDealInfo.PositionId();
result.commission = mDealInfo.Commission();
result.reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(
ticket,
DEAL_REASON);
//
return result;
}
//
// Convert an Order to XOrder by Index ...
XOrder ToXOrderByIndex(int index)
{
//
XOrder result = {};
//
bool isSelect = mOrderInfo.SelectByIndex(index);
if (!isSelect)
{
return result;
}
//
ulong ticket = mOrderInfo.Ticket();
result = ToXOrderByTicket(ticket);
//
return result;
}
//
// Convert an Order to XOrder by Ticket ...
XOrder ToXOrderByTicket(ulong ticket)
{
//
XOrder result = {};
//
bool isSelect = mOrderInfo.Select(ticket);
if (!isSelect)
{
return result;
}
//
result.state = mOrderInfo.State();
result.magic = mOrderInfo.Magic();
result.ticket = mOrderInfo.Ticket();
result.symbol = mOrderInfo.Symbol();
result.type = mOrderInfo.OrderType();
result.comment = mOrderInfo.Comment();
result.stopLoss = mOrderInfo.StopLoss();
result.typeTime = mOrderInfo.TypeTime();
result.timeDone = mOrderInfo.TimeDone();
result.timeSetup = mOrderInfo.TimeSetup();
result.positionId = mOrderInfo.PositionId();
result.priceOpen = mOrderInfo.PriceOpen();
result.takeProfit = mOrderInfo.TakeProfit();
result.typeFilling = mOrderInfo.TypeFilling();
result.priceCurrent = mOrderInfo.PriceCurrent();
result.volumeInitial = mOrderInfo.VolumeInitial();
result.volumeCurrent = mOrderInfo.VolumeCurrent();
result.timeExpiration = mOrderInfo.TimeExpiration();
result.priceStopLimit = mOrderInfo.PriceStopLimit();
result.reason = (ENUM_ORDER_REASON)HistoryOrderGetInteger(
ticket,
ORDER_REASON);
//
return result;
}
//
// END Signal Private ...
//
};
//
// END Global Definitions: Variables, Properties and etc ...
//