start implementing XTrade Handler Class ...

This commit is contained in:
2024-07-22 02:04:16 +03:30
parent d194d85082
commit d1e8daa131
5 changed files with 853 additions and 38 deletions
+84 -18
View File
@@ -46,18 +46,19 @@ public:
//
// Constructors ...
void XSCBaseStrategy(
string _symbol, // Trading Symbol
ENUM_TIMEFRAMES _period, // Trading TimeFrame
double _volume, // Voluem
double _r2r, // Risk/Reward Ratio
int _slippage, // Trader Slippage
long _magicNumber, // Trader Magic Number
bool _useTPSLAsPoint = false, // Converts TP and SL by Provided Points
bool _forceMaxTPSLAsPoint = false, // Force Max TP and SL by Provided Points
double _tpPoint = 0, // TP As Point
double _slPoint = 0, // SL As Point
bool _ignoreTP = false, // TP set to 0
bool _ignoreSL = false, // SL set to 0
string _symbol, // Trading Symbol
ENUM_TIMEFRAMES _period, // Trading TimeFrame
double _volume, // Voluem
double _r2r, // Risk/Reward Ratio
int _slippage, // Trader Slippage
long _magicNumber, // Trader Magic Number
bool _ignoreSignalExecution = false, // Ignore Signal Execution
bool _useTPSLAsPoint = false, // Converts TP and SL by Provided Points
bool _forceMaxTPSLAsPoint = false, // Force Max TP and SL by Provided Points
double _tpPoint = 0, // TP As Point
double _slPoint = 0, // SL As Point
bool _ignoreTP = false, // TP set to 0
bool _ignoreSL = false, // SL set to 0
bool _allowLong = true,
bool _allowShort = true,
int _maxAllowedLongs = 0,
@@ -82,6 +83,7 @@ public:
mMaxAllowedLongs = _maxAllowedLongs;
mMaxAllowedShorts = _maxAllowedShorts;
mForceMaxTPSLAsPoint = _forceMaxTPSLAsPoint;
mIgnoreSignalExecution = _ignoreSignalExecution;
//
mForceDisabled = false;
@@ -371,6 +373,29 @@ public:
mIgnoreSL = value;
}
//
bool IgnoreSignalExecution()
{
return mIgnoreSignalExecution;
}
//
void IgnoreSignalExecution(bool value)
{
mIgnoreSignalExecution = value;
}
//
// On Signal Handlers ...
void AddSignalEventHandler(TOnSignal handler)
{
//
Add(
handler,
mOnSignalEventHandlers //
);
}
//
// Virtual Methods ...
@@ -600,6 +625,18 @@ public:
signal.sl = 0;
}
//
// Notify Signal Event Handler(s) ...
NotifyOnSignalEventHandlers(signal);
//
// Check Signal Execution Enabled or not ...
result = !mIgnoreSignalExecution;
if (!result)
{
return result;
}
//
ENUM_X_SIGNAL_EXECUTION_RESULT state;
result = trader.ExecuteSignal(
@@ -652,12 +689,13 @@ protected:
int mMaxAllowedShorts; // Max Allowed Shorts
//
bool mUseTPSLAsPoint; // Converts TP and SL by Provided Points
bool mForceMaxTPSLAsPoint; // Force Max TP and SL by Provided Points
double mTPPoint; // TP As Point
double mSLPoint; // SL As Point
bool mIgnoreTP; // TP set to 0
bool mIgnoreSL; // SL set to 0
bool mUseTPSLAsPoint; // Converts TP and SL by Provided Points
bool mForceMaxTPSLAsPoint; // Force Max TP and SL by Provided Points
double mTPPoint; // TP As Point
double mSLPoint; // SL As Point
bool mIgnoreTP; // TP set to 0
bool mIgnoreSL; // SL set to 0
bool mIgnoreSignalExecution; // Ignore Signal Execution
//
string mSymbol; // Trading Symbol ...
@@ -687,11 +725,39 @@ protected:
barTracker.Clean();
}
//
// Notified Signal Event Handler(s) ...
void NotifyOnSignalEventHandlers(XSignal &signal)
{
//
if (!signal.IsValid())
{
return;
}
//
int count = ArraySize(mOnSignalEventHandlers);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
mOnSignalEventHandlers[i](signal);
}
}
//
// Private ...
private:
//
// Props ...
//
// On Signal Recieved Event Handler(s) ...
TOnSignal mOnSignalEventHandlers[];
};
//
+311
View File
@@ -22,6 +22,7 @@
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Classes/x-saherelm.xalert.class.mq5"
#include "../Libraries/x-saherelm.xtrade.lib.mq5"
#include "../Classes/x-saherelm.xaccount.class.mq5"
@@ -3772,4 +3773,314 @@ private:
}
};
//
// Trade Handler Class ...
class XSCXTradeHandler : public XSCBaseAlert
{
//
// Public ...
public:
//
//
// Constructor(s) ...
void XSCXTradeHandler(XSCTrade *trader)
{
//
mTrader = trader;
}
//
// Deconstructor ...
void ~XSCXTradeHandler()
{
//
delete mTrader;
}
//
// First Step of Trade Handling ...
// Since Must Call when a Signal Executed ...
void AddExecutedSignal(
XSignal &signal, // Executed Signal
double commission = 0 // Commission
)
{
//
// Check Signal Valid ...
if (!signal.IsValid())
{
return;
}
//
XTradeData item;
bool isFilled = item.Fill(signal);
if (!isFilled)
{
return;
}
//
item.commission = commission;
//
Add(item);
}
//
// this Method call's by a Timer,
// or in OnTick for Update Positions,
// Data ...
void UpdateData()
{
//
XPosition positions[];
int count = mTrader.GetPositions(positions);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XPosition iPosition = positions[i];
//
int idx = -1;
bool isExists = HasItem(
iPosition.ticket,
idx //
);
if (!isExists)
{
//
// Add New Data ...
//
// Find Executed Signal Deal History ...
XDeal deals[];
double commission = 0;
int dealsCount = mTrader.GetDeals(
deals,
iPosition.symbol,
iPosition.provider,
iPosition.period,
NULL,
DEAL_ENTRY_IN //
);
if (IsValidSize(dealsCount))
{
//
for (int i = 0; i < dealsCount; i++)
{
//
XDeal iDeal = deals[i];
if (iDeal.positionId == iPosition.ticket)
{
//
commission = iDeal.commission;
break;
}
}
}
//
XTradeData iData;
iData.Fill(
iPosition //
);
//
iData.ticket = iPosition.ticket;
//
Add(iData);
}
else
{
//
// Update Exists ...
mData[idx].Update(iPosition);
}
}
}
//
// Protected ...
protected:
//
XSCTrade *mTrader; // Instance of Trader Class
//
XTradeData mData[]; // Hold Trade Data
//
// Private ...
private:
//
// Props ...
//
// Count Data ...
int Count()
{
return ArraySize(mData);
}
//
// Add Item ...
bool Add(XTradeData &item)
{
//
bool result = false;
//
result = item.IsValid();
if (!result)
{
return result;
}
//
int index = -1;
if (item.ticket > 0)
{
//
result = !HasItem(
item.ticket,
index //
);
}
else
{
//
result = !HasItem(
item.symbol,
item.provider,
item.period,
item.type,
index //
);
}
if (!result || IsValidIndex(index))
{
//
result = false;
return result;
}
//
AddRef(
item,
mData //
);
//
return result;
}
//
// Find Item Index ...
bool HasItem(
ulong ticket,
int &index //
)
{
//
bool result = false;
//
index = -1;
//
int count = Count();
result = IsValidSize(count);
if (!result)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
result = mData[i].IsOwn(ticket);
if (result)
{
//
index = i;
break;
}
}
//
return result;
}
//
// Find Item Index ...
bool HasItem(
string symbol,
string provider,
ENUM_TIMEFRAMES period,
ENUM_X_POSITION_TYPES type,
int &index //
)
{
//
bool result = false;
//
index = -1;
//
// Validate ...
result =
//
IsValid(symbol) &&
IsValid(period) &&
IsValid(provider) &&
type != X_POSITION_TYPE_ALL &&
type != X_POSITION_TYPE_NONE
//
;
if (!result)
{
return result;
}
//
int count = Count();
result = IsValidSize(count);
if (!result)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
result = mData[i].IsOwn(
symbol,
provider,
period,
type //
);
if (result)
{
//
index = i;
break;
}
}
//
return result;
}
};
//
+86 -8
View File
@@ -67,6 +67,14 @@ XSCXCCHelper *mCCHelper;
// Registred Strategies ...
XSCBaseStrategy *strategies[];
//
// Trader Instance Class ...
XSCTrade *eaTrader;
//
// Trade Handler Instance Class ...
XSCXTradeHandler *eaTradeHandler;
//
// Event Handlers ...
@@ -90,7 +98,7 @@ int OnInit()
drawPrefix = ShortName;
//
// EventSetTimer(1);
EventSetTimer(5);
// EventSetMillisecondTimer(100);
//
@@ -120,7 +128,11 @@ void OnDeinit(const int reason)
delete mCCHelper;
//
// EventKillTimer();
delete eaTrader;
delete eaTradeHandler;
//
EventKillTimer();
//
Clean(strategies);
@@ -130,19 +142,14 @@ void OnDeinit(const int reason)
// On Tick Handler ...
void OnTick()
{
//
HandleStrategiesOnTick();
//
HandleTradeState();
}
//
// On Timer ...
void OnTimer()
{
//
// HandleStrategiesOnTick();
HandleTradeState();
}
//
@@ -199,6 +206,14 @@ bool InitialEA()
return result;
}
//
// Create Trader Instance ...
eaTrader = new XSCTrade(
eaSlippage,
eaMagicNumber //
);
eaTradeHandler = new XSCXTradeHandler(eaTrader);
//
XSymbolParser symbolParser;
@@ -241,6 +256,7 @@ bool InitialEA()
eaR2R, // R2R ...
eaSlippage,
magicNumber,
true, // Ignore Signal Execution
true, // Use TP SL Point
false, // Use Max
50, // eaTPPoint, // TP
@@ -254,6 +270,7 @@ bool InitialEA()
);
eurusdTestStrategy.SetAlertLogAlerts(true);
eurusdTestStrategy.SetAlertEnableAlerts(true);
eurusdTestStrategy.AddSignalEventHandler(OnSignalRecieved);
RegisterStrategy(eurusdTestStrategy);
}
}
@@ -307,6 +324,67 @@ void HandleTradeState()
{
//
// Implement All Trade States here ...
eaTradeHandler.UpdateData();
}
//
// All Signals from Strategies Comming Here for Execution or
// Analyzing ...
void OnSignalRecieved(XSignal &signal)
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT state;
bool isExecuted = eaTrader.ExecuteSignal(
signal,
state //
);
//
if (isExecuted)
{
//
// Find Executed Signal Deal History ...
XDeal deals[];
double commission = 0;
int dealsCount = eaTrader.GetDeals(
deals,
signal.symbol,
signal.provider,
signal.period,
NULL,
DEAL_ENTRY_IN //
);
if (IsValidSize(dealsCount))
{
//
for (int i = 0; i < dealsCount; i++)
{
//
XDeal iDeal = deals[i];
if (iDeal.positionId == signal.positionId)
{
//
commission = iDeal.commission;
break;
}
}
}
//
// Add Signal to Trade Handler ...
eaTradeHandler.AddExecutedSignal(
signal,
commission //
);
//
string msg = (signal.type == POSITION_TYPE_BUY ? "Long" : "Short") +
" Signal Provided by: " + signal.provider +
" on: " + signal.symbol +
" in: " + ToString(signal.period) +
" Executed Successfully ...";
Print(msg);
}
}
//
+358
View File
@@ -3379,9 +3379,367 @@ struct XSymbolPositions
//
};
//
// an Structure for Holding Positions Data ...
struct XTradeData
{
//
datetime time; // Issue Time (Open Position)
string symbol; // Trading Symbol
double entry; // Entry Price
double volume; // Volume
string provider; // Signaller
ENUM_TIMEFRAMES period; // Trading Timeframe
ENUM_X_POSITION_TYPES type; // Position Type
//
ulong ticket; // Position Ticket
double profit; // Profit on Close
double commission; // Commission
double swap; // Swap
string message; // Close Reason
datetime endTime; // End Time
//
// Constructor ...
void XTradeInfo()
{
Clean();
}
//
// Filling Trade Handler ...
bool Fill(XSignal &_signal)
{
//
bool result = false;
//
Clean();
//
// Check Signal Validation ...
result = _signal.IsValid();
if (!result)
{
return result;
}
//
time = _signal.time;
symbol = _signal.symbol;
entry = _signal.entry;
volume = _signal.volume;
provider = _signal.provider;
period = _signal.period;
type = ToPositionType(_signal.type);
//
if (_signal.IsExecuted())
{
ticket = _signal.positionId;
}
//
return result;
}
//
// Filling Trade Handler ...
bool Fill(XPosition &_position)
{
//
bool result = false;
//
Clean();
//
// Check Signal Validation ...
result = _position.IsValid();
if (!result)
{
return result;
}
//
time = _position.openAt;
symbol = _position.symbol;
entry = _position.entry;
volume = _position.volume;
provider = _position.provider;
period = _position.period;
type = ToPositionType(_position.type);
//
ticket = _position.ticket;
//
return result;
}
//
// Update Data ...
bool Update(XPosition &_position) {
//
bool result = false;
//
result = _position.IsValid();
if (!result) {
return result;
}
//
profit = _position.profit;
swap = _position.swap;
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
time = NULL;
type = NULL;
symbol = NULL;
period = NULL;
endTime = NULL;
message = NULL;
provider = NULL;
//
swap = 0;
entry = 0;
ticket = 0;
profit = 0;
volume = 0;
commission = 0;
}
//
// Validation ...
bool IsValid()
{
//
bool result = false;
//
result =
//
ticket > 0 &&
IsValid(time) &&
IsValid(symbol) &&
IsValid(period)
//
;
//
return result;
}
//
// Retrieve Trade Data Age ...
int GetAge()
{
//
int result = -1;
//
if (!IsValid(symbol) ||
!IsValid(time) ||
!IsValid(endTime) ||
!IsValid(period))
{
return result;
}
//
int startIndex = iBarShift(
symbol,
period,
time,
false //
);
//
int endIndex = iBarShift(
symbol,
period,
endTime,
false //
);
//
result = MathAbs(startIndex - endIndex);
//
return result;
}
//
// Check Own of Trade Data ...
// based on Ticket ...
bool IsOwn(
ulong _ticket //
)
{
//
bool result = false;
//
result = _ticket == ticket;
//
return result;
}
//
// Check Own of Trade Data ...
// based on Symbol/Provider and Period ...
bool IsOwn(
string _symbol,
string _provider,
ENUM_TIMEFRAMES _period,
ENUM_X_POSITION_TYPES _type //
)
{
//
bool result = false;
//
result =
//
IsValid(_symbol) &&
IsValid(_period) &&
IsValid(_provider) &&
type != X_POSITION_TYPE_ALL &&
type != X_POSITION_TYPE_NONE &&
//
type == _type &&
period == _period &&
symbol == _symbol &&
provider == _provider
//
;
//
return result;
}
//
// Data Collector ...
//
// Get Data File Name ...
string GetFileName()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
result =
//
symbol + "\\" +
ToString(type) + "\\" +
(profit >= 0 ? "Profit" : "Loss") +
ToString(ticket) + "_" +
ToString(period) + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
// Get Signal File Name ...
string GetSignalFileName()
{
//
string result = NULL;
//
result =
//
symbol + "\\" +
ToString(type) + "\\" +
provider + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
// Convert(s) To String Representation(s) ...
string ToString(
bool onlySignals = false //
)
{
//
string result = NULL;
//
int age = GetAge();
//
result =
//
(onlySignals ? "" : ToString("Ticket", ticket)) +
ToString("Symbol", symbol) +
ToString("Period", period) +
ToString("Entry", entry) +
ToString("Provider", provider) +
ToString("Type", ToString(type)) +
ToString("Time", time) +
(onlySignals
? ""
:
//
"-------------" + "\n" +
ToString("Volume", volume) +
ToString("Profit", profit) +
ToString("Commission", commission) +
ToString("Swap", swap) +
ToString("End Time", endTime) +
ToString("Age", age) +
ToString("Message", message)
//
) +
//
""
//
;
//
return result;
}
//
};
//
// TypeDefs ...
//
typedef void (*TOnSignal)(XSignal &signal);
//
typedef void (*TOnDealsChanged)(int count);
+14 -12
View File
@@ -53,18 +53,19 @@ public:
void XSCXTestStrategy(
//
// Base ...
string _symbol, // Trading Symbol
ENUM_TIMEFRAMES _period, // Trading TimeFrame
double _volume, // Voluem
double _r2r, // Risk/Reward Ratio
int _slippage, // Trader Slippage
long _magicNumber, // Trader Magic Number
bool _useTPSLAsPoint = false, // Converts TP and SL by Provided Points
bool _forceMaxTPSLAsPoint = false, // Force Max TP and SL by Provided Points
double _tpPoint = 0, // TP As Point
double _slPoint = 0, // SL As Point
bool _ignoreTP = false, // TP set to 0
bool _ignoreSL = false, // SL set to 0
string _symbol, // Trading Symbol
ENUM_TIMEFRAMES _period, // Trading TimeFrame
double _volume, // Voluem
double _r2r, // Risk/Reward Ratio
int _slippage, // Trader Slippage
long _magicNumber, // Trader Magic Number
bool _ignoreSignalExecution = false, // Ignore Signal Execution
bool _useTPSLAsPoint = false, // Converts TP and SL by Provided Points
bool _forceMaxTPSLAsPoint = false, // Force Max TP and SL by Provided Points
double _tpPoint = 0, // TP As Point
double _slPoint = 0, // SL As Point
bool _ignoreTP = false, // TP set to 0
bool _ignoreSL = false, // SL set to 0
bool _allowLong = true,
bool _allowShort = true,
int _maxAllowedLongs = 0,
@@ -75,6 +76,7 @@ public:
_r2r,
_slippage,
_magicNumber,
_ignoreSignalExecution,
_useTPSLAsPoint,
_forceMaxTPSLAsPoint,
_tpPoint,