2839 lines
68 KiB
Plaintext
2839 lines
68 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Expert Class Library
|
|
// ----------------------------------------------
|
|
// Name: XSCTrade
|
|
// Description: provides all Trade requirements ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// START Definitions ...
|
|
//
|
|
|
|
//
|
|
// Model an Open Position ...
|
|
struct XPosition
|
|
{
|
|
//
|
|
// Magic Number ...
|
|
ulong magic;
|
|
|
|
//
|
|
// Ticket ID ...
|
|
ulong ticket;
|
|
|
|
//
|
|
// Tradinng Symbol ...
|
|
string symbol;
|
|
|
|
//
|
|
// Trading Period ...
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
// Position Type ...
|
|
ENUM_POSITION_TYPE type;
|
|
|
|
//
|
|
// Take Profit ...
|
|
double tp;
|
|
|
|
//
|
|
// Stop Loss ...
|
|
double sl;
|
|
|
|
//
|
|
// Position Current Profit ...
|
|
double profit;
|
|
|
|
//
|
|
// Position Open Price ...
|
|
double entry;
|
|
|
|
//
|
|
// Current Symbol Price ...
|
|
double price;
|
|
|
|
//
|
|
// Position Swap ...
|
|
double swap;
|
|
|
|
//
|
|
// Position Commission ...
|
|
double commission;
|
|
|
|
//
|
|
// Volume ...
|
|
double volume;
|
|
|
|
//
|
|
// Position Open Time ...
|
|
datetime openAt;
|
|
|
|
//
|
|
// Position Comment ...
|
|
string comment;
|
|
};
|
|
|
|
//
|
|
// Model an Order ...
|
|
struct XOrder
|
|
{
|
|
//
|
|
// Time of order placement ...
|
|
datetime setupAt;
|
|
|
|
//
|
|
// Time of order expiration ...
|
|
datetime expiredAt;
|
|
|
|
//
|
|
// Time of order execution or cancellation ...
|
|
datetime executedAt;
|
|
|
|
//
|
|
// Order type ...
|
|
ENUM_ORDER_TYPE type;
|
|
|
|
//
|
|
// Order state ...
|
|
ENUM_ORDER_STATE state;
|
|
|
|
//
|
|
// Type of execution by remainder ...
|
|
ENUM_ORDER_TYPE_FILLING filling;
|
|
|
|
//
|
|
// Order lifetime ...
|
|
ENUM_ORDER_TYPE_TIME lifetime;
|
|
|
|
//
|
|
// Order ticket ...
|
|
ulong ticket;
|
|
|
|
//
|
|
// Magic Number ...
|
|
long magic;
|
|
|
|
//
|
|
// Position id, that is placed on order,
|
|
// when it is executed. Each executed order invokes a
|
|
// deal, that opens new or changes existing
|
|
// position. Id of that position is placed on
|
|
// executed order in this moment.
|
|
long pocitionID;
|
|
|
|
//
|
|
// Initial volume on order placement ...
|
|
double initialVolume;
|
|
|
|
//
|
|
// Unfilled volume ...
|
|
double currentVolume;
|
|
|
|
//
|
|
// Price, specified in the order ...
|
|
double openPrice;
|
|
|
|
//
|
|
// Current price by order symbol ...
|
|
double currentPrice;
|
|
|
|
//
|
|
// Price of placing Limit order when StopLimit order is triggered ...
|
|
double stopLimitPrice;
|
|
|
|
//
|
|
// Take Profit level ...
|
|
double tp;
|
|
|
|
//
|
|
// Stop Loss level ...
|
|
double sl;
|
|
|
|
//
|
|
// Trading Symbol ...
|
|
string smybol;
|
|
|
|
//
|
|
// Order Comment ...
|
|
string comment;
|
|
};
|
|
|
|
//
|
|
// Model a Deal ...
|
|
struct XDeal
|
|
{
|
|
//
|
|
// the ID of the Expert Advisor, that executed the deal ...
|
|
ulong magic;
|
|
|
|
//
|
|
// the ID of position, in which the deal was involved ...
|
|
ulong positionId;
|
|
|
|
//
|
|
// Ticket ...
|
|
ulong ticket;
|
|
|
|
//
|
|
// the name of the deal symbol ...
|
|
string symbol;
|
|
|
|
//
|
|
// order by which the deal is executed ...
|
|
ulong order;
|
|
|
|
//
|
|
// the time of deal execution ...
|
|
datetime time;
|
|
|
|
//
|
|
// Deal price ...
|
|
double price;
|
|
|
|
//
|
|
// the financial result of the deal (in deposit currency) ...
|
|
double profit;
|
|
|
|
//
|
|
// the amount of swap when position is closed ...
|
|
double swap;
|
|
|
|
//
|
|
// the amount of commission of the deal ...
|
|
double commission;
|
|
|
|
//
|
|
// the volume of deal ...
|
|
double volume;
|
|
|
|
//
|
|
// the deal comment ...
|
|
string comment;
|
|
|
|
//
|
|
// the deal type ...
|
|
// ------------------------------------------------------------------
|
|
// DEAL_TYPE_BUY => Buy ...
|
|
// DEAL_TYPE_SELL => Sell ...
|
|
// DEAL_TYPE_BUY_CANCELED => Canceled buy deal ...
|
|
// There can be a situation when a previously executed buy deal is canceled. In this case,
|
|
// the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED,
|
|
// and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ...
|
|
//
|
|
// DEAL_TYPE_SELL_CANCELED => Canceled sell deal ...
|
|
// There can be a situation when a previously executed sell deal is canceled. In this case,
|
|
// the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED,
|
|
// and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation
|
|
//
|
|
// DEAL_TYPE_BALANCE => Balance ...
|
|
// DEAL_TYPE_CREDIT => Credit ...
|
|
// DEAL_TYPE_CHARGE => Additional charge ...
|
|
// DEAL_TYPE_CORRECTION => Correction ...
|
|
// DEAL_TAX => Tax charges ...
|
|
// DEAL_TYPE_BONUS => Bonus ...
|
|
// DEAL_TYPE_INTEREST => Interest rate ...
|
|
// DEAL_DIVIDEND => Dividend operations...
|
|
// DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ...
|
|
// DEAL_TYPE_COMMISSION => Additional commission ...
|
|
// DEAL_TYPE_COMMISSION_DAILY => Daily commission ...
|
|
// DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ...
|
|
// DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ...
|
|
// DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission
|
|
ENUM_DEAL_TYPE type;
|
|
|
|
//
|
|
// the deal direction ...
|
|
// ----------------------------------
|
|
// DEAL_ENTRY_IN => Entry in ...
|
|
// DEAL_ENTRY_OUT => Entry out ...
|
|
// DEAL_ENTRY_INOUT => Reverse ...
|
|
// DEAL_ENTRY_OUT_BY => Close a position by an opposite one ...
|
|
ENUM_DEAL_ENTRY entry;
|
|
|
|
//
|
|
// deal reson ...
|
|
// ---------------------
|
|
// DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ...
|
|
// DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ...
|
|
// DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ...
|
|
// DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ...
|
|
// DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ...
|
|
// DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ...
|
|
// DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ...
|
|
// DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ...
|
|
// DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ...
|
|
// DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ...
|
|
ENUM_DEAL_REASON reason;
|
|
};
|
|
|
|
//
|
|
// END Definitions ...
|
|
//
|
|
|
|
//
|
|
// START Import and Inclused requirements ...
|
|
//
|
|
|
|
//
|
|
// Includes ...
|
|
#include <Trade/Trade.mqh>
|
|
#include "../Libraries/x-saherelm.log.lib.mq5"
|
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
|
|
|
//
|
|
// END Import and Inclused requirements ...
|
|
//
|
|
|
|
//
|
|
// START Overrides ...
|
|
//
|
|
|
|
//
|
|
// XCTrade Base Class ...
|
|
class XSCTradeBase : 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 ...
|
|
//
|
|
|
|
//
|
|
// a Class for Manage Trades ...
|
|
class XSCTrade
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Constructor ...
|
|
void XSCTrade(
|
|
int slippage, // Specify Slippage
|
|
ulong magicNumber // Specify Magic Number
|
|
)
|
|
{
|
|
//
|
|
mSlippage = slippage;
|
|
mMagicNumber = magicNumber;
|
|
|
|
//
|
|
mPeriodPrefix = "PR";
|
|
|
|
//
|
|
mTrader = new XSCTradeBase();
|
|
|
|
//
|
|
mTrader.SetAsyncMode(false);
|
|
mTrader.SetDeviationInPoints(mSlippage);
|
|
mTrader.SetExpertMagicNumber(mMagicNumber);
|
|
|
|
//
|
|
// Setting Log Level ...
|
|
mTrader.LogLevel(LOG_LEVEL_ERRORS);
|
|
|
|
//
|
|
// Prepare Trade Event Materials ...
|
|
mStartDate = 0;
|
|
mLastOrdersCount = OrdersTotal();
|
|
mLastDealsCount = HistoryDealsTotal();
|
|
mLastPositionsCount = PositionsTotal();
|
|
|
|
//
|
|
GetDeals(mLastDeals);
|
|
GetOrders(mLastOrders);
|
|
GetPositions(mLastPositions);
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XSCTrade()
|
|
{
|
|
}
|
|
|
|
//
|
|
// START Event Processing ...
|
|
//
|
|
|
|
//
|
|
// This Must be Called Every time OnTrade Event Happening ...
|
|
void HandleOnTrade()
|
|
{
|
|
//
|
|
int ordersCount = OrdersTotal();
|
|
int dealsCount = HistoryDealsTotal();
|
|
int positionsCount = PositionsTotal();
|
|
|
|
//
|
|
// LogMessage("Salam");
|
|
|
|
//
|
|
GetDeals(mDeals);
|
|
GetOrders(mOrders);
|
|
GetPositions(mPositions);
|
|
|
|
//
|
|
datetime currentTime = TimeCurrent();
|
|
HistorySelect(mStartDate, currentTime);
|
|
|
|
//
|
|
// Processing Positions ...
|
|
if (positionsCount > mLastPositionsCount)
|
|
{
|
|
//
|
|
// Position Appeared ...
|
|
LogMessage("Position Appeared ...");
|
|
|
|
//
|
|
// Update Deals ...
|
|
dealsCount = HistoryDealsTotal();
|
|
GetDeals(mDeals);
|
|
}
|
|
else if (positionsCount < mLastPositionsCount)
|
|
{
|
|
//
|
|
// Position Disappeared ...
|
|
LogMessage("Position Disappeared ...");
|
|
|
|
//
|
|
// Update Deals ...
|
|
dealsCount = HistoryDealsTotal();
|
|
GetDeals(mDeals);
|
|
}
|
|
|
|
//
|
|
// Processing Order Changes ...
|
|
if (ordersCount > mLastOrdersCount)
|
|
{
|
|
//
|
|
// Orders Appeared ...
|
|
LogMessage("Orders Appeared ...");
|
|
}
|
|
else if (ordersCount < mLastOrdersCount)
|
|
{
|
|
//
|
|
// Orders Disappeared ...
|
|
LogMessage("Orders Disappeared ...");
|
|
}
|
|
|
|
//
|
|
// Processing Deal Changes ...
|
|
if (dealsCount > mLastDealsCount)
|
|
{
|
|
//
|
|
// Deals Appeared ...
|
|
LogMessage("Deals Appeared ...");
|
|
}
|
|
else if (dealsCount > mLastDealsCount)
|
|
{
|
|
//
|
|
// Deals Disappeard ...
|
|
LogMessage("Deals Disappeard ...");
|
|
}
|
|
|
|
//
|
|
// Update Date after processing ...
|
|
|
|
//
|
|
mLastOrdersCount = OrdersTotal();
|
|
mLastDealsCount = HistoryDealsTotal();
|
|
mLastPositionsCount = PositionsTotal();
|
|
|
|
//
|
|
GetDeals(mLastDeals);
|
|
GetOrders(mLastOrders);
|
|
GetPositions(mLastPositions);
|
|
}
|
|
|
|
//
|
|
// END Event Processing ...
|
|
//
|
|
|
|
//
|
|
// START Provided Functions ...
|
|
//
|
|
|
|
//
|
|
// Count Currently Open Positions ...
|
|
int PositionsCount(
|
|
string symbol = "", // Specified Symbol
|
|
ENUM_POSITION_TYPE type = NULL // Specified Type
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
int allPositions = 0;
|
|
int longPositions = 0;
|
|
int shortPositions = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
string positionSymbol = mPositionInfo.Symbol();
|
|
|
|
//
|
|
ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType();
|
|
|
|
//
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
allPositions++;
|
|
|
|
//
|
|
continue;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == positionType &&
|
|
symbol == positionSymbol)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
longPositions++;
|
|
}
|
|
else
|
|
{
|
|
shortPositions++;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (positionSymbol == symbol)
|
|
{
|
|
//
|
|
allPositions++;
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == positionType)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
longPositions++;
|
|
}
|
|
else
|
|
{
|
|
shortPositions++;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Specify Result ...
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
result = allPositions;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
result = longPositions;
|
|
}
|
|
else
|
|
{
|
|
result = shortPositions++;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
result = allPositions;
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
result = longPositions;
|
|
}
|
|
else
|
|
{
|
|
result = shortPositions;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Max In Profit Position Ticket ...
|
|
ulong GetMaxInProfitPosition(
|
|
string symbol = "", // Specified Symbol
|
|
ENUM_POSITION_TYPE type = NULL // Specified Type
|
|
)
|
|
{
|
|
//
|
|
ulong result = -1;
|
|
|
|
//
|
|
double profit = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
|
|
//
|
|
string positionSymbol = mPositionInfo.Symbol();
|
|
|
|
//
|
|
double positionProfit = mPositionInfo.Profit();
|
|
double positionAbsProfit = MathAbs(positionProfit);
|
|
if (positionProfit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType();
|
|
|
|
//
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == positionType &&
|
|
symbol == positionSymbol)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (positionSymbol == symbol)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == positionType)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Max In DrawDown Position Ticket ...
|
|
ulong GetMaxInDrawDownPosition(
|
|
string symbol = "", // Specified Symbol
|
|
ENUM_POSITION_TYPE type = NULL // Specified Type
|
|
)
|
|
{
|
|
//
|
|
ulong result = -1;
|
|
|
|
//
|
|
double profit = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
|
|
//
|
|
string positionSymbol = mPositionInfo.Symbol();
|
|
|
|
//
|
|
double positionProfit = mPositionInfo.Profit();
|
|
double positionAbsProfit = MathAbs(positionProfit);
|
|
if (positionProfit >= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType();
|
|
|
|
//
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == positionType &&
|
|
symbol == positionSymbol)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (positionSymbol == symbol)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == positionType)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionAbsProfit)
|
|
{
|
|
//
|
|
result = positionTicket;
|
|
profit = positionAbsProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specific Position's Profit ...
|
|
double GetPositionProfit(
|
|
const ulong ticket // Specified Position Ticket
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
if (positionTicket != ticket)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = mPositionInfo.Profit();
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specific Position's OpenDate ...
|
|
datetime GetPositionOpenDate(
|
|
const ulong ticket // Specified Position Ticket
|
|
)
|
|
{
|
|
//
|
|
datetime result = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
if (positionTicket != ticket)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = mPositionInfo.Time();
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specific Position's Comment ...
|
|
string GetPositionComment(
|
|
const ulong ticket // Specified Position Ticket
|
|
)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
if (positionTicket != ticket)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = mPositionInfo.Comment();
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve All Open Positions Profit ...
|
|
double GetPositionsProfit(
|
|
string symbol = "", // Specified Symbol
|
|
ENUM_POSITION_TYPE type = NULL // Specified Type
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
double profit = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
|
|
//
|
|
string positionSymbol = mPositionInfo.Symbol();
|
|
|
|
//
|
|
double positionProfit = mPositionInfo.Profit();
|
|
|
|
//
|
|
ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType();
|
|
|
|
//
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == positionType &&
|
|
symbol == positionSymbol)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (positionSymbol == symbol)
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == positionType)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (profit < positionProfit)
|
|
{
|
|
//
|
|
result += positionProfit;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Oldes Position ...
|
|
ulong GetOldestPosition(
|
|
string symbol = "", // Specified Symbol
|
|
ENUM_POSITION_TYPE type = NULL // Specified Type
|
|
)
|
|
{
|
|
//
|
|
ulong result = 0;
|
|
|
|
//
|
|
int age = 0;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
|
|
//
|
|
string positionSymbol = mPositionInfo.Symbol();
|
|
|
|
//
|
|
double positionProfit = mPositionInfo.Profit();
|
|
double positionAbsProfit = MathAbs(positionProfit);
|
|
if (positionProfit >= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ENUM_POSITION_TYPE positionType = mPositionInfo.PositionType();
|
|
|
|
//
|
|
string positionComment = mPositionInfo.Comment();
|
|
ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(positionComment);
|
|
|
|
//
|
|
// Calculate Position's Age ...
|
|
datetime positionOpenTime = mPositionInfo.Time();
|
|
|
|
//
|
|
// Retrieve Trade Open Bar Index based on Current Period ...
|
|
int positionOpenBarIndex = iBarShift(
|
|
positionSymbol,
|
|
positionPeriod,
|
|
positionOpenTime);
|
|
|
|
//
|
|
// Calculate Trade Life ...
|
|
int positionAge = MathAbs(0 - positionOpenBarIndex);
|
|
|
|
//
|
|
if (
|
|
type == NULL &&
|
|
StringLen(symbol) <= 0)
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
else if (
|
|
type != NULL &&
|
|
StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (type == positionType &&
|
|
symbol == positionSymbol)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (StringLen(symbol) > 0)
|
|
{
|
|
//
|
|
if (positionSymbol == symbol)
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else if (type != NULL)
|
|
{
|
|
//
|
|
if (type == positionType)
|
|
{
|
|
//
|
|
if (type == POSITION_TYPE_BUY)
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (age < positionAge)
|
|
{
|
|
//
|
|
age = positionAge;
|
|
result = positionTicket;
|
|
}
|
|
}
|
|
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Force Open a Buy/Long Position ...
|
|
bool Buy(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
double volume, // position volume
|
|
double price, // execution price
|
|
double sl = 0, // stop loss price
|
|
double tp = 0, // take profit price
|
|
string comment = "" // comment
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.Buy(
|
|
volume,
|
|
symbol,
|
|
price,
|
|
sl,
|
|
tp,
|
|
comment);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Send BUY LIMIT order ...
|
|
bool BuyLimit(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
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;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.BuyLimit(
|
|
volume,
|
|
price,
|
|
symbol,
|
|
sl,
|
|
tp,
|
|
typeTime,
|
|
expiration,
|
|
comment);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Send BUY STOP order ...
|
|
bool BuyStop(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
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;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.BuyStop(
|
|
volume,
|
|
price,
|
|
symbol,
|
|
sl,
|
|
tp,
|
|
typeTime,
|
|
expiration,
|
|
comment);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Force Open a Sell/Short Position ...
|
|
bool Sell(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
double volume, // position volume
|
|
double price, // execution price
|
|
double sl = 0, // stop loss price
|
|
double tp = 0, // take profit price
|
|
string comment = "" // comment
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.Sell(
|
|
volume,
|
|
symbol,
|
|
price,
|
|
sl,
|
|
tp,
|
|
comment);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Send SELL LIMIT order ...
|
|
bool SellLimit(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
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;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.SellLimit(
|
|
volume,
|
|
price,
|
|
symbol,
|
|
sl,
|
|
tp,
|
|
typeTime,
|
|
expiration,
|
|
comment);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Send SELL STOP order ...
|
|
bool SellStop(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES period, // Specified Trade's Period
|
|
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;
|
|
|
|
//
|
|
string mPeriodStr = GeneratePositionPeriodComment(period);
|
|
|
|
//
|
|
comment += mPeriodStr;
|
|
|
|
//
|
|
result = mTrader.SellStop(
|
|
volume,
|
|
price,
|
|
symbol,
|
|
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
|
|
string comment = "" // comment
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (tp <= 0 && sl <= 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Use Position Comment when there isn't new One ...
|
|
if (StringLen(comment) == 0)
|
|
{
|
|
comment = GetPositionComment(ticket);
|
|
}
|
|
|
|
//
|
|
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);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Close All Positions ...
|
|
void CloseAllPositions(
|
|
string comment = "" // Close Position By Specific Comment
|
|
)
|
|
{
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
Close(
|
|
positionTicket,
|
|
comment);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Find Position Open Bar Index ...
|
|
int GetPositionOpenBarIndex(
|
|
const ulong ticket // position ticket
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong positionTicket = mPositionInfo.Ticket();
|
|
if (positionTicket != ticket)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
string symbol = mPositionInfo.Symbol();
|
|
datetime openAt = mPositionInfo.Time();
|
|
string comment = mPositionInfo.Comment();
|
|
ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment);
|
|
|
|
//
|
|
result = iBarShift(
|
|
symbol,
|
|
period,
|
|
openAt);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Positions as an Array ...
|
|
void GetPositions(
|
|
XPosition &result[] // Hold Result ...
|
|
)
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mPositionInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ulong magic = mPositionInfo.Magic();
|
|
ulong ticket = mPositionInfo.Ticket();
|
|
string symbol = mPositionInfo.Symbol();
|
|
datetime openAt = mPositionInfo.Time();
|
|
double swap = mPositionInfo.Swap();
|
|
double sl = mPositionInfo.StopLoss();
|
|
double tp = mPositionInfo.TakeProfit();
|
|
double profit = mPositionInfo.Profit();
|
|
double volume = mPositionInfo.Volume();
|
|
string comment = mPositionInfo.Comment();
|
|
double entry = mPositionInfo.PriceOpen();
|
|
double price = mPositionInfo.PriceCurrent();
|
|
double commission = mPositionInfo.Commission();
|
|
ENUM_POSITION_TYPE type = mPositionInfo.PositionType();
|
|
ENUM_TIMEFRAMES period = ExtractPositionPeriod(comment);
|
|
|
|
//
|
|
XPosition iPosition = {};
|
|
|
|
//
|
|
iPosition.tp = tp;
|
|
iPosition.sl = sl;
|
|
iPosition.swap = swap;
|
|
iPosition.type = type;
|
|
iPosition.magic = magic;
|
|
iPosition.entry = entry;
|
|
iPosition.price = price;
|
|
iPosition.ticket = ticket;
|
|
iPosition.symbol = symbol;
|
|
iPosition.period = period;
|
|
iPosition.volume = volume;
|
|
iPosition.openAt = openAt;
|
|
iPosition.profit = profit;
|
|
iPosition.comment = comment;
|
|
iPosition.commission = commission;
|
|
|
|
//
|
|
Add(
|
|
iPosition,
|
|
result);
|
|
}
|
|
}
|
|
|
|
//
|
|
void GetPositions(
|
|
XPosition &result[], // Hold Result ...
|
|
string symbol, // Trading Symbol ...
|
|
ENUM_TIMEFRAMES period // Trading Period ...
|
|
)
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XPosition allPositions[];
|
|
GetPositions(allPositions);
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = allPositions[i];
|
|
|
|
//
|
|
if (symbol != iPosition.symbol)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ENUM_TIMEFRAMES positionPeriod = ExtractPositionPeriod(iPosition.comment);
|
|
if (period != positionPeriod)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iPosition,
|
|
result);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve in Profit Positions ...
|
|
void GetInProfitPositions(
|
|
XPosition &result[] // Hold Result ...
|
|
)
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
XPosition allPositions[];
|
|
GetPositions(allPositions);
|
|
int positionsCount = ArraySize(allPositions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = allPositions[i];
|
|
|
|
//
|
|
if (iPosition.profit > 0)
|
|
{
|
|
Add(
|
|
iPosition,
|
|
result);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve in Drawdown Positions ...
|
|
void GetInDrawdownPositions(
|
|
XPosition &result[] // Hold Result ...
|
|
)
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
XPosition allPositions[];
|
|
GetPositions(allPositions);
|
|
int positionsCount = ArraySize(allPositions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = allPositions[i];
|
|
|
|
//
|
|
if (iPosition.profit < 0)
|
|
{
|
|
Add(
|
|
iPosition,
|
|
result);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close a Collection Of Positions ...
|
|
void ClosePositions(
|
|
XPosition &positions[], // Positions to Close ...
|
|
string comment = "" // Specified Comment ...
|
|
)
|
|
{
|
|
//
|
|
int positionsCount = ArraySize(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
Close(
|
|
iPosition.ticket,
|
|
comment);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve All Orders ...
|
|
void GetOrders(XOrder &result[])
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
int ordersCount = OrdersTotal();
|
|
if (ordersCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Since Orders may be so more than positions ...
|
|
// start Orders Collectiong Loops reverse ...
|
|
for (int i = ordersCount - 1; i >= 0; i--)
|
|
{
|
|
//
|
|
if (!mPositionInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mOrderInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Order Info ...
|
|
long magic = mOrderInfo.Magic();
|
|
double sl = mOrderInfo.StopLoss();
|
|
ulong ticket = mOrderInfo.Ticket();
|
|
double tp = mOrderInfo.TakeProfit();
|
|
string smybol = mOrderInfo.Symbol();
|
|
string comment = mOrderInfo.Comment();
|
|
long pocitionID = mOrderInfo.PositionId();
|
|
double openPrice = mOrderInfo.PriceOpen();
|
|
datetime setupAt = mOrderInfo.TimeSetup();
|
|
datetime executedAt = mOrderInfo.TimeDone();
|
|
ENUM_ORDER_STATE state = mOrderInfo.State();
|
|
ENUM_ORDER_TYPE type = mOrderInfo.OrderType();
|
|
double currentPrice = mOrderInfo.PriceCurrent();
|
|
datetime expiredAt = mOrderInfo.TimeExpiration();
|
|
double initialVolume = mOrderInfo.VolumeInitial();
|
|
double currentVolume = mOrderInfo.VolumeCurrent();
|
|
double stopLimitPrice = mOrderInfo.PriceStopLimit();
|
|
ENUM_ORDER_TYPE_TIME lifetime = mOrderInfo.TypeTime();
|
|
ENUM_ORDER_TYPE_FILLING filling = mOrderInfo.TypeFilling();
|
|
|
|
//
|
|
// Now Create an instance of XOrder struct and fill it by
|
|
// retrieved data, and add it to results ...
|
|
XOrder iOrder = {};
|
|
|
|
//
|
|
iOrder.sl = sl;
|
|
iOrder.tp = tp;
|
|
iOrder.type = type;
|
|
iOrder.state = state;
|
|
iOrder.magic = magic;
|
|
iOrder.ticket = ticket;
|
|
iOrder.smybol = smybol;
|
|
iOrder.setupAt = setupAt;
|
|
iOrder.comment = comment;
|
|
iOrder.filling = filling;
|
|
iOrder.lifetime = lifetime;
|
|
iOrder.expiredAt = expiredAt;
|
|
iOrder.openPrice = openPrice;
|
|
iOrder.pocitionID = pocitionID;
|
|
iOrder.executedAt = executedAt;
|
|
iOrder.currentPrice = currentPrice;
|
|
iOrder.initialVolume = initialVolume;
|
|
iOrder.currentVolume = currentVolume;
|
|
iOrder.stopLimitPrice = stopLimitPrice;
|
|
|
|
//
|
|
Add(
|
|
iOrder,
|
|
result);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve All Deals ...
|
|
void GetDeals(XDeal &result[])
|
|
{
|
|
//
|
|
Clear(result);
|
|
|
|
//
|
|
int dealsCount = HistoryDealsTotal();
|
|
if (dealsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = dealsCount - 1; i >= 0; i--)
|
|
{
|
|
//
|
|
if (!mDealInfo.SelectByIndex(i))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (mDealInfo.Magic() != mMagicNumber)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Order Info ...
|
|
double swap = mDealInfo.Swap();
|
|
ulong magic = mDealInfo.Magic();
|
|
ulong order = mDealInfo.Order();
|
|
ulong ticket = mDealInfo.Ticket();
|
|
datetime time = mDealInfo.Time();
|
|
double price = mDealInfo.Price();
|
|
string symbol = mDealInfo.Symbol();
|
|
double profit = mDealInfo.Profit();
|
|
double volume = mDealInfo.Volume();
|
|
string comment = mDealInfo.Comment();
|
|
ulong positionId = mDealInfo.PositionId();
|
|
ENUM_DEAL_ENTRY entry = mDealInfo.Entry();
|
|
double commission = mDealInfo.Commission();
|
|
ENUM_DEAL_TYPE type = mDealInfo.DealType();
|
|
ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(
|
|
ticket,
|
|
DEAL_REASON);
|
|
|
|
//
|
|
XDeal iDeal = {};
|
|
|
|
//
|
|
iDeal.swap = swap;
|
|
iDeal.time = time;
|
|
iDeal.type = type;
|
|
iDeal.magic = magic;
|
|
iDeal.entry = entry;
|
|
iDeal.order = order;
|
|
iDeal.price = price;
|
|
iDeal.ticket = ticket;
|
|
iDeal.symbol = symbol;
|
|
iDeal.profit = profit;
|
|
iDeal.volume = volume;
|
|
iDeal.reason = reason;
|
|
iDeal.comment = comment;
|
|
iDeal.positionId = positionId;
|
|
iDeal.commission = commission;
|
|
|
|
//
|
|
Add(
|
|
iDeal,
|
|
result);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Generate String Representation Of Position's Time Frame ...
|
|
string GeneratePositionPeriodComment(ENUM_TIMEFRAMES period)
|
|
{
|
|
//
|
|
string result = mPeriodPrefix + "(" + ToString(period) + ")";
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Position Time Frame From it's Comment ...
|
|
ENUM_TIMEFRAMES ExtractPositionPeriod(string comment)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
if (StringLen(comment) <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string periodStr = ExtractString(
|
|
comment,
|
|
mPeriodPrefix + "(",
|
|
")");
|
|
if (StringLen(periodStr) <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ToPeriod(periodStr);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Last Open Position Ticket ...
|
|
ulong GetLastOpenPositionTicket()
|
|
{
|
|
//
|
|
ulong result = 0;
|
|
|
|
int positionsCount = PositionsTotal();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = PositionGetTicket(PositionsTotal() - 1);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Provided Functions ...
|
|
//
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// using deviation, it must be in Point ...
|
|
int mSlippage;
|
|
|
|
//
|
|
// using magic number ...
|
|
ulong mMagicNumber;
|
|
|
|
//
|
|
// using CTrade instance ...
|
|
XSCTradeBase mTrader;
|
|
|
|
//
|
|
// Deals Info ...
|
|
CDealInfo mDealInfo;
|
|
|
|
//
|
|
// Order Info ...
|
|
COrderInfo mOrderInfo;
|
|
|
|
//
|
|
// using PositionInfo instance ...
|
|
CPositionInfo mPositionInfo;
|
|
|
|
//
|
|
// ADDITIONAL Data ...
|
|
|
|
//
|
|
string mPeriodPrefix;
|
|
|
|
//
|
|
// Trade Processing ...
|
|
datetime mStartDate;
|
|
int mLastDealsCount;
|
|
int mLastOrdersCount;
|
|
int mLastPositionsCount;
|
|
//
|
|
XDeal mDeals[];
|
|
XOrder mOrders[];
|
|
XPosition mPositions[];
|
|
//
|
|
XDeal mLastDeals[];
|
|
XOrder mLastOrders[];
|
|
XPosition mLastPositions[];
|
|
};
|
|
|
|
//
|
|
// START Usefull Functions ...
|
|
//
|
|
|
|
//
|
|
// Add Specific XPosition to Specified Array ...
|
|
void Add(
|
|
XDeal &item,
|
|
XDeal &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XOrder &item,
|
|
XOrder &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XPosition &item,
|
|
XPosition &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
|
|
//
|
|
// Clear All Items Inside Array ...
|
|
void Clear(XDeal &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void Clear(XOrder &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void Clear(XPosition &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
|
|
//
|
|
// END Usefull Functions ...
|
|
//
|