694 lines
13 KiB
Plaintext
694 lines
13 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XCXSTRCCITradeManager
|
|
// Description: provides all Requirements for Managing Trades ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-alert.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-trade.class.mq5"
|
|
#include "../Libraries/xstrcci.signaller.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
enum ENUM_XSTRCCI_TRADE_FINALIZATION
|
|
{
|
|
XSTRCCI_TRADE_FINAL_NONE,
|
|
XSTRCCI_TRADE_FINAL_TP,
|
|
XSTRCCI_TRADE_FINAL_SL,
|
|
XSTRCCI_TRADE_FINAL_CLOSE_IN_PROFIT,
|
|
XSTRCCI_TRADE_FINAL_CLOSE_IN_LOSE,
|
|
};
|
|
|
|
//
|
|
struct XSTRCCITrade
|
|
{
|
|
//
|
|
// Props ...
|
|
double swap;
|
|
double profit;
|
|
XSignal signal;
|
|
ulong positionID;
|
|
double commission;
|
|
XSTRCCIStrategyConditions conditions;
|
|
ENUM_XSTRCCI_TRADE_FINALIZATION finalize;
|
|
|
|
//
|
|
// Constructor ...
|
|
XSTRCCITrade()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup Model ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
swap = 0;
|
|
profit = 0;
|
|
signal.Clean();
|
|
commission = 0;
|
|
positionID = 0;
|
|
conditions.Clean();
|
|
finalize = XSTRCCI_TRADE_FINAL_NONE;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Check Has Signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = signal.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Signal Executed or Not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsExecuted()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = positionID > 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Trade is Finalized or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsFinalized()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = HasSignal() &&
|
|
IsExecuted() &&
|
|
finalize != XSTRCCI_TRADE_FINAL_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCXSTRCCITradeManager : public XCBaseAlert
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
XCTrade *trader;
|
|
bool drawSignal;
|
|
XCPOIDrawer *drawer;
|
|
|
|
//
|
|
// Constructors ...
|
|
XCXSTRCCITradeManager(XCTrade *&_trader)
|
|
{
|
|
//
|
|
trader = _trader;
|
|
drawSignal = true;
|
|
drawer = new XCPOIDrawer();
|
|
}
|
|
|
|
//
|
|
// De Constructors ...
|
|
~XCXSTRCCITradeManager()
|
|
{
|
|
//
|
|
ZeroMemory(trader);
|
|
ZeroMemory(drawer);
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Do All Position Managing Senaros ...
|
|
*/
|
|
void Manage()
|
|
{
|
|
//
|
|
bool has = HasChild(trades);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(trades);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = trades[i].IsExecuted() &&
|
|
!trades[i].IsFinalized();
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XPosition iPosition;
|
|
has = trader.GetPosition(
|
|
trades[i].positionID,
|
|
iPosition //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Update Trade Data ...
|
|
trades[i].swap = iPosition.swap;
|
|
trades[i].profit = iPosition.profit;
|
|
}
|
|
|
|
//
|
|
// After Update All Trades we can Do Protection ...
|
|
Protect();
|
|
}
|
|
|
|
/**
|
|
* Do All Position Protection Here ...
|
|
*/
|
|
void Protect()
|
|
{
|
|
//
|
|
bool has = HasChild(trades);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XPosition ownPosition[];
|
|
XPosition ownLongPosition[];
|
|
XPosition ownShortPosition[];
|
|
|
|
//
|
|
int count = ArraySize(trades);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has =
|
|
trades[i].IsExecuted() &&
|
|
!trades[i].IsFinalized();
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XPosition iPosition;
|
|
has = trader.GetPosition(
|
|
trades[i].positionID,
|
|
iPosition //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
iPosition,
|
|
ownPosition //
|
|
);
|
|
|
|
//
|
|
if (IsLong(iPosition.type))
|
|
{
|
|
//
|
|
AddRef(
|
|
iPosition,
|
|
ownLongPosition //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddRef(
|
|
iPosition,
|
|
ownShortPosition //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
has = HasChild(ownPosition);
|
|
if (!has)
|
|
{
|
|
//
|
|
Clean(ownPosition);
|
|
Clean(ownLongPosition);
|
|
Clean(ownShortPosition);
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
double swapSum = 0;
|
|
double profitSum = 0;
|
|
double commissionSum = 0;
|
|
|
|
//
|
|
// Calculate Required Data On Collection ...
|
|
count = ArraySize(ownPosition);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownPosition[i];
|
|
|
|
//
|
|
swapSum += iPosition.swap;
|
|
profitSum += iPosition.profit;
|
|
commissionSum += iPosition.commission;
|
|
}
|
|
|
|
//
|
|
// Do Collection Protectiong ...
|
|
// TODO: Implement this ...
|
|
|
|
//
|
|
// Do Signle Protections ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Select Position ...
|
|
XPosition iPosition = ownPosition[i];
|
|
|
|
//
|
|
// Handle RF ...
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute Specified Signal ...
|
|
*
|
|
* @param signal: XSignal instance reference ...
|
|
* @param conditions: XSTRCCIStrategyConditions instance reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Execute(
|
|
XSignal &signal,
|
|
XSTRCCIStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = signal.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
bool isExists = HasTrade(
|
|
idx,
|
|
signal //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_SIGNAL_EXECUTION_RESULT executionResult;
|
|
result = trader.ExecuteSignal(
|
|
signal,
|
|
executionResult //
|
|
);
|
|
|
|
//
|
|
// Alert Signal Execution ...
|
|
string executionMessage = ToString(executionResult);
|
|
Alert(executionMessage);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
if (drawSignal)
|
|
{
|
|
//
|
|
XCSignalObject *iObj;
|
|
isExists = drawer.DrawSignal(
|
|
signal,
|
|
iObj //
|
|
);
|
|
|
|
//
|
|
if (isExists)
|
|
{
|
|
//
|
|
mObjects.Add(iObj);
|
|
ZeroMemory(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
XSTRCCITrade iTrade;
|
|
|
|
//
|
|
ulong positionID = trader.GetLastOpenPositionTicket();
|
|
double commission = trader.GetPositionCommission(positionID);
|
|
|
|
//
|
|
iTrade.signal = signal;
|
|
iTrade.conditions = conditions;
|
|
iTrade.positionID = positionID;
|
|
iTrade.commission = commission;
|
|
|
|
//
|
|
AddRef(
|
|
iTrade,
|
|
trades //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Handle Position Take Profit ...
|
|
*
|
|
* @param deal: XDeal instance reference ...
|
|
*/
|
|
void HandleTP(const XDeal &deal)
|
|
{
|
|
//
|
|
// Check Ticket Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = HasTrade(
|
|
idx,
|
|
deal.positionId //
|
|
);
|
|
if (!isExists)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Apply Required Data ...
|
|
trades[idx].swap = deal.swap;
|
|
trades[idx].profit = deal.profit;
|
|
trades[idx].commission = deal.commission;
|
|
trades[idx].finalize = XSTRCCI_TRADE_FINAL_TP;
|
|
|
|
//
|
|
tpCount++;
|
|
managedTPCount++;
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Handle Position Stop Loss ...
|
|
*
|
|
* @param deal: XDeal instance reference ...
|
|
*/
|
|
void HandleSL(const XDeal &deal)
|
|
{
|
|
//
|
|
// Check Ticket Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = HasTrade(
|
|
idx,
|
|
deal.positionId //
|
|
);
|
|
if (!isExists)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Apply Required Data ...
|
|
trades[idx].swap = deal.swap;
|
|
trades[idx].profit = deal.profit;
|
|
trades[idx].commission = deal.commission;
|
|
trades[idx].finalize = XSTRCCI_TRADE_FINAL_SL;
|
|
|
|
//
|
|
slCount++;
|
|
managedSLCount++;
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Handle Position Force Close ...
|
|
*
|
|
* @param deal: XDeal instance reference ...
|
|
*/
|
|
void HandleForceClose(const XPosition &position)
|
|
{
|
|
//
|
|
// Check Ticket Exists or not ...
|
|
int idx = -1;
|
|
bool isExists = HasTrade(
|
|
idx,
|
|
position.ticket //
|
|
);
|
|
if (!isExists)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isInProfit = position.profit > 0;
|
|
|
|
//
|
|
// Apply Required Data ...
|
|
trades[idx].swap = position.swap;
|
|
trades[idx].profit = position.profit;
|
|
trades[idx].commission = position.commission;
|
|
trades[idx].finalize = isInProfit
|
|
? XSTRCCI_TRADE_FINAL_CLOSE_IN_PROFIT
|
|
: XSTRCCI_TRADE_FINAL_CLOSE_IN_LOSE;
|
|
|
|
//
|
|
if (isInProfit)
|
|
{
|
|
//
|
|
tpCount++;
|
|
managedTPCount++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
slCount++;
|
|
managedSLCount++;
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
void HandleGuard()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Find Executed Trade by Providing Position Ticket ...
|
|
*
|
|
* @param index: int reference, holding founded item index ...
|
|
* @param ticket: ulong, Specified Position Ticket ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasTrade(
|
|
int &index,
|
|
ulong ticket //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
result =
|
|
ticket > 0 &&
|
|
HasChild(trades);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(trades);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSTRCCITrade iTrade = trades[i];
|
|
|
|
//
|
|
result =
|
|
iTrade.HasSignal() &&
|
|
iTrade.IsExecuted() &&
|
|
iTrade.positionID == ticket;
|
|
if (result)
|
|
{
|
|
//
|
|
index = i;
|
|
|
|
//
|
|
iTrade.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iTrade.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Trade Item By Signal ...
|
|
*
|
|
* @param index: int reference, holding founded item index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasTrade(
|
|
int &index,
|
|
XSignal &signal //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
result =
|
|
signal.IsValid() &&
|
|
HasChild(trades);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(trades);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSTRCCITrade iTrade = trades[i];
|
|
|
|
//
|
|
result =
|
|
iTrade.HasSignal() &&
|
|
iTrade.signal.IsSameAs(signal);
|
|
if (result)
|
|
{
|
|
//
|
|
index = i;
|
|
|
|
//
|
|
iTrade.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iTrade.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
int slCount;
|
|
int tpCount;
|
|
|
|
//
|
|
int managedSLCount;
|
|
int managedTPCount;
|
|
|
|
//
|
|
CArrayObj mObjects;
|
|
|
|
//
|
|
XSTRCCITrade trades[];
|
|
};
|
|
|
|
//
|