1506 lines
33 KiB
Plaintext
1506 lines
33 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\OrderInfo.mqh>
|
|
#include <Trade\AccountInfo.mqh>
|
|
#include <Trade\PositionInfo.mqh>
|
|
#include <Trade\HistoryOrderInfo.mqh>
|
|
#include "x-saherelm.models.lib.mq5"
|
|
//
|
|
// END Model Definitions ...
|
|
//
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
//
|
|
// XSaherElm Trade Class ...
|
|
class XCTrade
|
|
{
|
|
//
|
|
// all public features ...
|
|
public:
|
|
//
|
|
// Constructor ...
|
|
void XCTrade(
|
|
string symbol,
|
|
int slippage,
|
|
ulong magicNumber)
|
|
{
|
|
//
|
|
mSymbol = symbol;
|
|
mSlippage = slippage;
|
|
mMagicNumber = magicNumber;
|
|
|
|
//
|
|
mTrader = new CTrade();
|
|
|
|
//
|
|
mTrader.SetAsyncMode(false);
|
|
mTrader.SetDeviationInPoints(mSlippage);
|
|
mTrader.SetExpertMagicNumber(mMagicNumber);
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCTrade()
|
|
{
|
|
}
|
|
|
|
//
|
|
// 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 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;
|
|
}
|
|
|
|
//
|
|
// Retrieve all Positions ...
|
|
void GetAllPositions(XSignal &result[])
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
|
|
//
|
|
int total = Count();
|
|
ArrayResize(result, total);
|
|
|
|
//
|
|
int filledIndex = 0;
|
|
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;
|
|
}
|
|
|
|
//
|
|
result[filledIndex] = PositionToSignal(i);
|
|
filledIndex++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve all Long Positions ...
|
|
void GetLongPositions(XSignal &result[])
|
|
{
|
|
GetAllPositionsByType(POSITION_TYPE_BUY, result);
|
|
}
|
|
|
|
//
|
|
// Retrieve all Short Positions ...
|
|
void GetShortPositions(XSignal &result[])
|
|
{
|
|
GetAllPositionsByType(POSITION_TYPE_SELL, result);
|
|
}
|
|
|
|
//
|
|
// Get All Trades Which Candle Passed after Open ...
|
|
void GetLongTimeTrades(
|
|
int life, // Max Candle Passed after Trades Open
|
|
ENUM_TIMEFRAMES period, // Calculate Candles based on time frame
|
|
XSignal &result[] // Holds Result
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
// Normalize Period ...
|
|
if (period == EMPTY_VALUE)
|
|
{
|
|
period = _Period;
|
|
}
|
|
|
|
//
|
|
XSignal positions[];
|
|
GetAllPositions(positions);
|
|
int count = ArraySize(positions);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Current Time Frame Candle Index ...
|
|
int currentBarIndex = 0;
|
|
|
|
//
|
|
// Loop through Positions ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = positions[i];
|
|
|
|
//
|
|
// Retrieve Trade Open Bar Index based on Current Period ...
|
|
int tradeOpenBarIndex = iBarShift(
|
|
mSymbol,
|
|
period,
|
|
trade.time);
|
|
|
|
//
|
|
// Calculate Trade Life ...
|
|
int diff = MathAbs(currentBarIndex - tradeOpenBarIndex);
|
|
if (diff >= life)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get In DrawDown Trades ...
|
|
void GetInDrawDownTrades(
|
|
double maxDrawDown, // Maximum DrawDown which trades going to close if bigger than or equal it
|
|
ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed
|
|
XSignal &result[] // Holds Result
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (maxDrawDown <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal trades[];
|
|
|
|
//
|
|
// Retrieve Signals ...
|
|
if (
|
|
type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG &&
|
|
type != X_SIGNAL_SHORT))
|
|
{
|
|
GetAllPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_LONG)
|
|
{
|
|
GetLongPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_SHORT)
|
|
{
|
|
GetShortPositions(trades);
|
|
}
|
|
|
|
//
|
|
// Check Trades Count ...
|
|
int count = ArraySize(trades);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop through all retrieved trades ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = trades[i];
|
|
if (trade.profit > 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPassed = (-1 * trade.profit) >= maxDrawDown;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get In Profit Trades ...
|
|
void GetInProfitTrades(
|
|
double minProfit, // Minimum Profit To Close Trades
|
|
ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed
|
|
XSignal &result[] // Holds Result
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, 0);
|
|
|
|
//
|
|
XSignal trades[];
|
|
|
|
//
|
|
// Retrieve Signals ...
|
|
if (
|
|
type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG &&
|
|
type != X_SIGNAL_SHORT))
|
|
{
|
|
GetAllPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_LONG)
|
|
{
|
|
GetLongPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_SHORT)
|
|
{
|
|
GetShortPositions(trades);
|
|
}
|
|
|
|
//
|
|
// Check Trades Count ...
|
|
int count = ArraySize(trades);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop through all retrieved trades ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = trades[i];
|
|
if (trade.profit < 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPassed = minProfit <= 0 ? true : trade.profit >= minProfit;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(result) + 1);
|
|
result[ArraySize(result) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Validate Signal ...
|
|
bool ValidateSignal(XSignal &signal)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Execute an Specific XSignal instance ...
|
|
bool ExecuteSignal(XSignal &signal)
|
|
{
|
|
//
|
|
bool result = ValidateSignal(signal);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
signal.symbol = mSymbol;
|
|
|
|
//
|
|
result = signal.type == X_SIGNAL_LONG ? Buy(
|
|
signal.volume,
|
|
signal.entry,
|
|
signal.sl,
|
|
signal.tp,
|
|
signal.comment)
|
|
: signal.type == X_SIGNAL_SHORT ? Sell(
|
|
signal.volume,
|
|
signal.entry,
|
|
signal.sl,
|
|
signal.tp,
|
|
signal.comment)
|
|
: false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Modify Position ...
|
|
bool Modify(
|
|
const ulong ticket, // position ticket
|
|
double sl = 0, // stop loss price
|
|
double tp = 0 // take profit
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (tp <= 0 && sl <= 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = mTrader.PositionModify(
|
|
ticket,
|
|
sl,
|
|
tp);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Close Position By Ticket ...
|
|
bool Close(ulong ticket)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Try to Select Position ...
|
|
if (!mPositionInfo.SelectByTicket(ticket))
|
|
{
|
|
//
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = mTrader.PositionClose(ticket);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Close Partial By Ticket ...
|
|
bool ClosePartial(ulong ticket, double volume)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (!mPositionInfo.SelectByTicket(ticket))
|
|
{
|
|
//
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mTrader.PositionClosePartial(
|
|
ticket,
|
|
volume);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Close All Positions ...
|
|
void CloseAllPositions(
|
|
XSignal &closed[] // holds Closed Positions
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
// Count all Specified Positions ...
|
|
int total = Count();
|
|
if (total <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal allPositions[];
|
|
GetAllPositions(allPositions);
|
|
|
|
//
|
|
int allPositionsSize = ArraySize(allPositions);
|
|
if (allPositionsSize == 0 || allPositionsSize != total)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < total; i++)
|
|
{
|
|
//
|
|
XSignal signal = allPositions[i];
|
|
bool isClosed = Close(signal.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = signal;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All Longs Positions ...
|
|
void CloseLongPositions(
|
|
XSignal &closed[] // holds Closed Positions
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
// Count all Specified Positions ...
|
|
int total = CountLongs();
|
|
if (total <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal longPositions[];
|
|
GetLongPositions(longPositions);
|
|
|
|
//
|
|
int longPositionsSize = ArraySize(longPositions);
|
|
if (longPositionsSize == 0 || longPositionsSize != total)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < total; i++)
|
|
{
|
|
//
|
|
XSignal signal = longPositions[i];
|
|
bool isClosed = Close(signal.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = signal;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All Shorts Positions ...
|
|
void CloseShortPositions(
|
|
XSignal &closed[] // holds Closed Positions
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
// Count all Specified Positions ...
|
|
int total = CountShorts();
|
|
if (total <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal shortPositions[];
|
|
GetShortPositions(shortPositions);
|
|
|
|
//
|
|
int shortPositionsSize = ArraySize(shortPositions);
|
|
if (shortPositionsSize == 0 || shortPositionsSize != total)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < total; i++)
|
|
{
|
|
//
|
|
XSignal signal = shortPositions[i];
|
|
bool isClosed = Close(signal.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = signal;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All Trades Which Candle Passed after Open ...
|
|
void CloseLongTimeTrades(
|
|
int life, // Max Candle Passed after Trades Open
|
|
ENUM_TIMEFRAMES period, // Calculate Candles based on time frame
|
|
XSignal &closed[] // holds Closed Trades ...
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
// Normalize Period ...
|
|
if (period == EMPTY_VALUE)
|
|
{
|
|
period = _Period;
|
|
}
|
|
|
|
//
|
|
XSignal positions[];
|
|
GetAllPositions(positions);
|
|
int count = ArraySize(positions);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Current Time Frame Candle Index ...
|
|
int currentBarIndex = 0;
|
|
|
|
//
|
|
// Loop through Positions ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = positions[i];
|
|
|
|
//
|
|
// Retrieve Trade Open Bar Index based on Current Period ...
|
|
int tradeOpenBarIndex = iBarShift(
|
|
mSymbol,
|
|
period,
|
|
trade.time);
|
|
|
|
//
|
|
// Calculate Trade Life ...
|
|
int diff = MathAbs(currentBarIndex - tradeOpenBarIndex);
|
|
if (diff >= life)
|
|
{
|
|
bool isClosed = Close(trade.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close In DrawDown Trades ...
|
|
void CloseInDrawDownTrades(
|
|
double maxDrawDown, // Maximum DrawDown which trades going to close if bigger than or equal it
|
|
ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed
|
|
XSignal &closed[] // holds Closed Trades ...
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (maxDrawDown <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XSignal trades[];
|
|
|
|
//
|
|
// Retrieve Signals ...
|
|
if (
|
|
type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG &&
|
|
type != X_SIGNAL_SHORT))
|
|
{
|
|
GetAllPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_LONG)
|
|
{
|
|
GetLongPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_SHORT)
|
|
{
|
|
GetShortPositions(trades);
|
|
}
|
|
|
|
//
|
|
// Check Trades Count ...
|
|
int count = ArraySize(trades);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop through all retrieved trades ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = trades[i];
|
|
if (trade.profit > 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPassed = (-1 * trade.profit) >= maxDrawDown;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
bool isClosed = Close(trade.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All In Profit Trades ...
|
|
void CloseInProfitTrades(
|
|
double minProfit, // Minimum Profit To Close Trades
|
|
ENUM_X_SIGNAL_TYPE type, // specify trades type to close, if none all tardes which in max drawdown was closed
|
|
XSignal &closed[] // holds Closed Trades ...
|
|
)
|
|
{
|
|
//
|
|
ArrayFree(closed);
|
|
ArrayResize(closed, 0);
|
|
|
|
//
|
|
XSignal trades[];
|
|
|
|
//
|
|
// Retrieve Signals ...
|
|
if (
|
|
type == X_SIGNAL_UNKNOWN || (type != X_SIGNAL_LONG &&
|
|
type != X_SIGNAL_SHORT))
|
|
{
|
|
GetAllPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_LONG)
|
|
{
|
|
GetLongPositions(trades);
|
|
}
|
|
else if (type == X_SIGNAL_SHORT)
|
|
{
|
|
GetShortPositions(trades);
|
|
}
|
|
|
|
//
|
|
// Check Trades Count ...
|
|
int count = ArraySize(trades);
|
|
if (count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop through all retrieved trades ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal trade = trades[i];
|
|
if (trade.profit < 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPassed = minProfit <= 0 ? true : trade.profit >= minProfit;
|
|
if (isPassed)
|
|
{
|
|
//
|
|
bool isClosed = Close(trade.ticket);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
closed,
|
|
ArraySize(closed) + 1);
|
|
closed[ArraySize(closed) - 1] = trade;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// all protected features ...
|
|
protected:
|
|
//
|
|
// all private features ...
|
|
private:
|
|
//
|
|
// which Symbol ...
|
|
string mSymbol;
|
|
|
|
//
|
|
// using deviation, it must be in Point ...
|
|
int mSlippage;
|
|
|
|
//
|
|
// using magic number ...
|
|
ulong mMagicNumber;
|
|
|
|
//
|
|
// using CTrade instance ...
|
|
CTrade mTrader;
|
|
|
|
//
|
|
// using PositionInfo instance ...
|
|
CPositionInfo mPositionInfo;
|
|
|
|
//
|
|
// using OrderInfo instance ...
|
|
COrderInfo mPendingInfo;
|
|
|
|
//
|
|
// using HistoryOrderInfo instance ...
|
|
CHistoryOrderInfo mHistoryInfo;
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Convert Position to Signal by Index ...
|
|
XSignal PositionToSignal(int index)
|
|
{
|
|
//
|
|
XSignal result = {};
|
|
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(index))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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();
|
|
|
|
//
|
|
// Ticket ...
|
|
result.ticket = mPositionInfo.Ticket();
|
|
|
|
//
|
|
// Entry/Open Price ...
|
|
result.entry = mPositionInfo.PriceOpen();
|
|
|
|
//
|
|
// Take Profit ...
|
|
result.tp = mPositionInfo.TakeProfit();
|
|
|
|
//
|
|
// Stop Loss ...
|
|
result.sl = mPositionInfo.StopLoss();
|
|
|
|
//
|
|
// Profit ...
|
|
result.profit = mPositionInfo.Profit();
|
|
|
|
//
|
|
// Time ...
|
|
result.time = mPositionInfo.Time();
|
|
|
|
//
|
|
// Volume ...
|
|
result.volume = mPositionInfo.Volume();
|
|
|
|
//
|
|
// Comment ...
|
|
result.comment = mPositionInfo.Comment();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Convert Position to Signal by Index ...
|
|
XSignal OrderToSignal(int index)
|
|
{
|
|
//
|
|
XSignal result = {};
|
|
|
|
//
|
|
if (!mHistoryInfo.SelectByIndex(index))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// ID ...
|
|
result.id = mHistoryInfo.PositionId();
|
|
|
|
//
|
|
// Symbol ...
|
|
result.symbol = mHistoryInfo.Symbol();
|
|
|
|
//
|
|
// Type ...
|
|
ENUM_ORDER_TYPE pType = (ENUM_ORDER_TYPE)mHistoryInfo.OrderType();
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN;
|
|
switch (pType)
|
|
{
|
|
//
|
|
case ORDER_TYPE_BUY:
|
|
case ORDER_TYPE_BUY_LIMIT:
|
|
case ORDER_TYPE_BUY_STOP:
|
|
case ORDER_TYPE_BUY_STOP_LIMIT:
|
|
type = X_SIGNAL_LONG;
|
|
break;
|
|
|
|
//
|
|
case ORDER_TYPE_SELL:
|
|
case ORDER_TYPE_SELL_LIMIT:
|
|
case ORDER_TYPE_SELL_STOP:
|
|
case ORDER_TYPE_SELL_STOP_LIMIT:
|
|
type = X_SIGNAL_SHORT;
|
|
break;
|
|
|
|
//
|
|
// Default ...
|
|
default:
|
|
type = X_SIGNAL_UNKNOWN;
|
|
break;
|
|
}
|
|
result.type = type;
|
|
|
|
//
|
|
// MagicNumber ...
|
|
result.magicNumber = mHistoryInfo.Magic();
|
|
|
|
//
|
|
// Ticket ...
|
|
result.ticket = mHistoryInfo.Ticket();
|
|
|
|
//
|
|
// Entry/Open Price ...
|
|
result.entry = mHistoryInfo.PriceOpen();
|
|
|
|
//
|
|
// Take Profit ...
|
|
result.tp = mHistoryInfo.TakeProfit();
|
|
|
|
//
|
|
// Stop Loss ...
|
|
result.sl = mHistoryInfo.StopLoss();
|
|
|
|
//
|
|
// Profit ...
|
|
// TODO Calculate it ...
|
|
// result.profit = mHistoryInfo.Profit();
|
|
|
|
// //
|
|
// // Time ...
|
|
// result.time = mHistoryInfo.Time();
|
|
|
|
// //
|
|
// // Volume ...
|
|
// result.volume = mHistoryInfo.Volume();
|
|
|
|
//
|
|
// Comment ...
|
|
result.comment = mHistoryInfo.Comment();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get all Positions based on Position Type ...
|
|
void GetAllPositionsByType(ENUM_POSITION_TYPE type, XSignal &result[])
|
|
{
|
|
//
|
|
int existsTotal = CountByType(type);
|
|
|
|
//
|
|
ArrayFree(result);
|
|
ArrayResize(result, existsTotal);
|
|
|
|
//
|
|
int filledIndex = 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;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.PositionType() != type)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result[filledIndex] = PositionToSignal(i);
|
|
filledIndex++;
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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) ...
|
|
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;
|
|
};
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|