last ...
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include <Generic/HashMap.mqh>
|
||||
#include "../Classes/x-saherelm.xea.class.mq5"
|
||||
#include "../Classes/x-saherelm.x121.provider.class.mq5"
|
||||
|
||||
@@ -29,6 +30,450 @@
|
||||
// Define On Signal Event Handler Type Specified for X5 ...
|
||||
typedef void (*TX121OnSignal)(X121ProviderDescriptor &descriptor);
|
||||
|
||||
//
|
||||
class XSCPositionHolder
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
// Constructor(s) ...
|
||||
|
||||
//
|
||||
XSCPositionHolder()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Cleanup ...
|
||||
void Clear()
|
||||
{
|
||||
Clean(mItems);
|
||||
}
|
||||
|
||||
//
|
||||
bool AddItem(XPosition &item)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = item.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = !HasItem(item);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
AddRef(
|
||||
item,
|
||||
mItems //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int AddItems(XPosition &items[])
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
int itemsCount = ArraySize(items);
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = items[i];
|
||||
|
||||
//
|
||||
bool isAdded = AddItem(iItem);
|
||||
if (isAdded)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool AddOrUpdateItem(XPosition &item)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = item.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool hasItem = HasItem(item);
|
||||
if (!hasItem)
|
||||
{
|
||||
result = AddItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
result = RemoveItem(item);
|
||||
if (result)
|
||||
{
|
||||
result = AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int AddOrUpdateItem(XPosition &items[])
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
int itemsCount = ArraySize(items);
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = items[i];
|
||||
|
||||
//
|
||||
bool isAddOrUpdated = AddOrUpdateItem(iItem);
|
||||
if (isAddOrUpdated)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool HasItem(XPosition &item)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
int itemIDX = FindItem(item);
|
||||
result = itemIDX >= 0;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int FindItem(XPosition &item)
|
||||
{
|
||||
//
|
||||
int result = -1;
|
||||
|
||||
//
|
||||
if (!item.IsValid())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int itemsCount = CountItems();
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = mItems[i];
|
||||
|
||||
//
|
||||
bool isSame = IsItemSameAs(item, iItem);
|
||||
if (isSame)
|
||||
{
|
||||
//
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool GetByIndex(
|
||||
int index,
|
||||
XPosition &item //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
NormalizeIndex(
|
||||
index,
|
||||
mItems //
|
||||
);
|
||||
|
||||
//
|
||||
item = mItems[index];
|
||||
|
||||
//
|
||||
result = item.IsValid();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool RemoveItem(XPosition &item)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = HasItem(item);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int itemIDX = FindItem(item);
|
||||
result = ArrayRemove(
|
||||
mItems,
|
||||
itemIDX,
|
||||
1 //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int RemoveItems(XPosition &items[])
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
int itemsCount = ArraySize(items);
|
||||
if (itemsCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = items[i];
|
||||
|
||||
//
|
||||
bool isRemoved = RemoveItem(iItem);
|
||||
if (isRemoved)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int CountItems()
|
||||
{
|
||||
return ArraySize(mItems);
|
||||
}
|
||||
|
||||
//
|
||||
bool IsItemSameAs(
|
||||
XPosition &source,
|
||||
XPosition &dest // Compare Source with this ...
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
dest.IsValid() &&
|
||||
source.IsValid() &&
|
||||
source.symbol == dest.symbol &&
|
||||
source.period == dest.period &&
|
||||
source.ticket == dest.ticket &&
|
||||
source.openAt == dest.openAt &&
|
||||
source.provider == dest.provider
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Custom Functions ...
|
||||
|
||||
//
|
||||
bool GetMaxInDrawdown(
|
||||
XPosition &item // Result
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
item.Clean();
|
||||
|
||||
//
|
||||
int itemsCount = CountItems();
|
||||
result = IsValidSize(itemsCount);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int maxIDX = -1;
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = mItems[i];
|
||||
|
||||
//
|
||||
bool canSelect =
|
||||
//
|
||||
iItem.profit < 0
|
||||
//
|
||||
&&
|
||||
//
|
||||
(
|
||||
//
|
||||
(maxIDX == -1 && !item.IsValid())
|
||||
? true
|
||||
: item.profit < iItem.profit
|
||||
//
|
||||
)
|
||||
//
|
||||
;
|
||||
if (canSelect)
|
||||
{
|
||||
//
|
||||
maxIDX = i;
|
||||
item = iItem;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result = maxIDX > -1 && item.IsValid();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool GetMaxInProfit(
|
||||
XPosition &item // Result
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
item.Clean();
|
||||
|
||||
//
|
||||
int itemsCount = CountItems();
|
||||
result = IsValidSize(itemsCount);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int maxIDX = -1;
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
{
|
||||
//
|
||||
XPosition iItem = mItems[i];
|
||||
|
||||
//
|
||||
bool canSelect =
|
||||
//
|
||||
iItem.profit > 0
|
||||
//
|
||||
&&
|
||||
//
|
||||
(
|
||||
//
|
||||
(maxIDX == -1 && !item.IsValid())
|
||||
? true
|
||||
: item.profit < iItem.profit
|
||||
//
|
||||
)
|
||||
//
|
||||
;
|
||||
if (canSelect)
|
||||
{
|
||||
//
|
||||
maxIDX = i;
|
||||
item = iItem;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result = maxIDX > -1 && item.IsValid();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Props ...
|
||||
XPosition mItems[];
|
||||
};
|
||||
|
||||
//
|
||||
// Class Definition ...
|
||||
|
||||
@@ -51,6 +496,7 @@ public:
|
||||
double maxAllowedSpread, // Max Allowed Spred for Opening Trades
|
||||
int maxAllowedPositions, // Max Allowed Positions
|
||||
double maxAllowedDrawdownFactor, // Max Allowed Drawdown Factor
|
||||
double staticVolume, // Static Volume for Positions
|
||||
//
|
||||
// Position Management ...
|
||||
bool allowLong = true, // Allow Long Trades
|
||||
@@ -80,6 +526,7 @@ public:
|
||||
maxAllowedSpread,
|
||||
maxAllowedPositions,
|
||||
maxAllowedDrawdownFactor,
|
||||
staticVolume,
|
||||
allowLong,
|
||||
allowShort,
|
||||
minProfitPerTrade,
|
||||
@@ -501,9 +948,8 @@ public:
|
||||
// TODO:
|
||||
// Make them Configurable ...
|
||||
int levelsOnClose = 6;
|
||||
int requiredAgeForSLTrail = 0;
|
||||
int requiredDistanceForSLTrail = 100;
|
||||
return;
|
||||
int requiredAgeForTrail = 0;
|
||||
int requiredDistanceForTrail = 5;
|
||||
|
||||
//
|
||||
int positionsCount = ArraySize(positions);
|
||||
@@ -531,7 +977,7 @@ public:
|
||||
if (canManageState)
|
||||
{
|
||||
//
|
||||
// Check Position in Profit or not ...
|
||||
// When Position in Profit, Trail SL ...
|
||||
if (iPosition.profit > 0)
|
||||
{
|
||||
//
|
||||
@@ -550,7 +996,7 @@ public:
|
||||
//
|
||||
// Check Position Age ...
|
||||
int iPositionAge = iPosition.GetAge(iPosition.period);
|
||||
if (iPositionAge < requiredAgeForSLTrail)
|
||||
if (iPositionAge < requiredAgeForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -559,7 +1005,7 @@ public:
|
||||
// Check Position Profit Distance ...
|
||||
double priceDistanceInPoint = PriceToPoint(iPosition.profit / iPosition.volume, iPosition.symbol);
|
||||
double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol);
|
||||
if (priceDistance < requiredDistanceForSLTrail)
|
||||
if (priceDistance < requiredDistanceForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -568,17 +1014,17 @@ public:
|
||||
double slDiff = PointToPrice(priceDistance, iPosition.symbol);
|
||||
double appliedSL = slDiff / 2;
|
||||
|
||||
// //
|
||||
// double sl =
|
||||
// IsLong(iPosition.type)
|
||||
// ? iPosition.sl + slDiff
|
||||
// : iPosition.sl - slDiff;
|
||||
|
||||
//
|
||||
double sl =
|
||||
IsLong(iPosition.type)
|
||||
? iPosition.entry + appliedSL
|
||||
: iPosition.entry - appliedSL;
|
||||
? iPosition.sl + slDiff
|
||||
: iPosition.sl - slDiff;
|
||||
|
||||
//
|
||||
// double sl =
|
||||
// IsLong(iPosition.type)
|
||||
// ? iPosition.entry + appliedSL
|
||||
// : iPosition.entry - appliedSL;
|
||||
|
||||
//
|
||||
bool isInit = trail.Init(
|
||||
@@ -614,7 +1060,7 @@ public:
|
||||
trail.time,
|
||||
false //
|
||||
);
|
||||
if (age < requiredAgeForSLTrail)
|
||||
if (age < requiredAgeForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -622,7 +1068,7 @@ public:
|
||||
//
|
||||
double priceDistanceInPoint = PriceToPoint((iPosition.profit - trail.profit) / iPosition.volume, iPosition.symbol);
|
||||
double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol);
|
||||
if (priceDistance < (requiredDistanceForSLTrail / 2))
|
||||
if (priceDistance < (requiredDistanceForTrail / 2))
|
||||
{
|
||||
// //
|
||||
// // int positionAge = iPosition.GetAge(iPosition.period);
|
||||
@@ -660,15 +1106,18 @@ public:
|
||||
double appliedSL = slDiff / 2;
|
||||
|
||||
//
|
||||
double selectedValue =
|
||||
//
|
||||
trail.level == 1 || (isLong
|
||||
? iPosition.sl < iPosition.entry
|
||||
: iPosition.sl > iPosition.entry)
|
||||
? iPosition.entry
|
||||
: iPosition.sl
|
||||
//
|
||||
;
|
||||
double selectedValue = iPosition.sl;
|
||||
|
||||
// //
|
||||
// double selectedValue =
|
||||
// //
|
||||
// trail.level == 1 || (isLong
|
||||
// ? iPosition.sl < iPosition.entry
|
||||
// : iPosition.sl > iPosition.entry)
|
||||
// ? iPosition.entry
|
||||
// : iPosition.sl
|
||||
// //
|
||||
// ;
|
||||
|
||||
//
|
||||
double sl =
|
||||
@@ -713,6 +1162,142 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// When Position in Drawdown Trail TP ...
|
||||
if (iPosition.profit < 0)
|
||||
{
|
||||
//
|
||||
XTrail trail;
|
||||
bool isTrailedBefore = GetTPTrail(
|
||||
iPosition.ticket,
|
||||
trail //
|
||||
);
|
||||
|
||||
//
|
||||
if (!isTrailedBefore)
|
||||
{
|
||||
//
|
||||
// Add First Time ...
|
||||
|
||||
//
|
||||
// Check Position Age ...
|
||||
int iPositionAge = iPosition.GetAge(iPosition.period);
|
||||
if (iPositionAge < requiredAgeForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Position Profit Distance ...
|
||||
double priceDistanceInPoint = PriceToPoint(MathAbs(iPosition.profit) / iPosition.volume, iPosition.symbol);
|
||||
double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol);
|
||||
if (priceDistance < requiredDistanceForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
double tpDiff = PointToPrice(priceDistance, iPosition.symbol);
|
||||
|
||||
//
|
||||
double tp =
|
||||
IsLong(iPosition.type)
|
||||
? iPosition.tp - tpDiff
|
||||
: iPosition.tp + tpDiff;
|
||||
|
||||
//
|
||||
bool isInit = trail.Init(
|
||||
iPosition.ticket,
|
||||
iPosition.type,
|
||||
iPosition.profit,
|
||||
iPosition.tp,
|
||||
tp //
|
||||
);
|
||||
if (!isInit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Update Exists ...
|
||||
|
||||
//
|
||||
// Check Profit ...
|
||||
bool isProfitPassed = MathAbs(iPosition.profit) > MathAbs(trail.profit);
|
||||
if (!isProfitPassed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Age Distance from Last ...
|
||||
int age = iBarShift(
|
||||
iPosition.symbol,
|
||||
iPosition.period,
|
||||
trail.time,
|
||||
false //
|
||||
);
|
||||
if (age < requiredAgeForTrail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
double priceDistanceInPoint = PriceToPoint((MathAbs(iPosition.profit) - MathAbs(trail.profit)) / iPosition.volume, iPosition.symbol);
|
||||
double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol);
|
||||
|
||||
//
|
||||
bool isLong = IsLong(iPosition.type);
|
||||
|
||||
//
|
||||
double tpDiff = PointToPrice(priceDistance, iPosition.symbol);
|
||||
|
||||
//
|
||||
double tp =
|
||||
isLong
|
||||
? iPosition.tp - tpDiff
|
||||
: iPosition.tp + tpDiff;
|
||||
|
||||
//
|
||||
// Update Trail Values ...
|
||||
bool isUpdated = trail.Update(
|
||||
tp,
|
||||
iPosition.profit //
|
||||
);
|
||||
if (!isUpdated)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (trail.IsValid())
|
||||
{
|
||||
//
|
||||
string comment = trail.GenerateTag();
|
||||
bool isModified = mTrader.Modify(
|
||||
trail.ticket,
|
||||
iPosition.sl,
|
||||
trail.after,
|
||||
comment //
|
||||
);
|
||||
if (isModified)
|
||||
{
|
||||
//
|
||||
RemoveTrail(trail.ticket);
|
||||
|
||||
//
|
||||
AddTPTrail(trail);
|
||||
|
||||
//
|
||||
string message = "Position (" + ToString(trail.ticket) + ") Trailed TP on Level: " + ToString(trail.level);
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -745,8 +1330,6 @@ public:
|
||||
// Cleaning Source ...
|
||||
Clean(signals);
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// Loop through Signals for Management ...
|
||||
for (int i = 0; i < tmpsCount; i++)
|
||||
@@ -755,6 +1338,7 @@ public:
|
||||
XSignal iSignal = tmps[i];
|
||||
|
||||
//
|
||||
// dont Manage NON Signal Provider's signals ...
|
||||
string provider = iSignal.provider;
|
||||
if (!IsValid(provider))
|
||||
{
|
||||
@@ -777,13 +1361,23 @@ public:
|
||||
NULL, // All Periods ...
|
||||
iSignal.type //
|
||||
);
|
||||
XPosition symbolPositions[];
|
||||
int positionsCount = mTrader.GetPositions(
|
||||
positions,
|
||||
iSignal.symbol,
|
||||
NULL, // All Providers ...
|
||||
NULL, // All Periods ...
|
||||
iSignal.type //
|
||||
);
|
||||
double profit = CalculatePositionsProfit(positions);
|
||||
double symbolProfit = CalculatePositionsProfit(symbolPositions);
|
||||
if (positionsCount <= 0)
|
||||
{
|
||||
//
|
||||
// First Signal in a While of Specific Provider ...
|
||||
|
||||
//
|
||||
iSignal.volume *= 2;
|
||||
// iSignal.volume *= 2;
|
||||
|
||||
//
|
||||
AddRef(
|
||||
@@ -808,6 +1402,14 @@ public:
|
||||
//
|
||||
continue;
|
||||
}
|
||||
else if (profit > 0 && symbolProfit > 0)
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
iSignal,
|
||||
signals //
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -838,9 +1440,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Management Tracker/Profit etc ...
|
||||
|
||||
//
|
||||
// Handle Position Changed Event ...
|
||||
void OnPositionsChangedHandler(int count)
|
||||
void OnPositionsChangedHandler(int count) override
|
||||
{
|
||||
//
|
||||
// Synchronize Tracker ...
|
||||
@@ -848,77 +1456,135 @@ public:
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
//
|
||||
// Position Tracker ...
|
||||
|
||||
//
|
||||
// Synchronize Positions and Position Tracker ...
|
||||
void SyncPositionTracker()
|
||||
// Called when a Position Going in Profit ...
|
||||
void OnPositionGoingInProfit(XPositionTrack &track) override
|
||||
{
|
||||
//
|
||||
static datetime lastSyncPositionTracker = NULL;
|
||||
datetime cTime = TimeCurrent();
|
||||
string message = "Position (" + ToString(track.ticket) + ", " + track.symbol + ") Dropped in Profit ...";
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
|
||||
//
|
||||
// Called when a Position Going to Drawdown ...
|
||||
void OnPositionGoingToDrawdown(XPositionTrack &track) override
|
||||
{
|
||||
//
|
||||
string message = "Position (" + ToString(track.ticket) + ", " + track.symbol + ") Dropped in Drawdown ...";
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
|
||||
//
|
||||
// Called when Account Going in Profit ...
|
||||
void OnGoingToProfit(XProfitTrack &track) override
|
||||
{
|
||||
//
|
||||
string message = "Account In Profit ...";
|
||||
|
||||
//
|
||||
int syncInterval = PeriodSeconds(PERIOD_M5);
|
||||
int lastDiff = (int)cTime - (int)lastSyncPositionTracker;
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
|
||||
//
|
||||
// Called when Account Going in Drawdown ...
|
||||
void OnGoingToDrawdown(XProfitTrack &track) override
|
||||
{
|
||||
//
|
||||
string message = "Account In Drawdown ...";
|
||||
|
||||
//
|
||||
bool canSync =
|
||||
lastSyncPositionTracker == NULL
|
||||
? true
|
||||
: lastDiff >= syncInterval;
|
||||
if (!canSync)
|
||||
mAlert.Alert(message);
|
||||
|
||||
//
|
||||
// Here i Have to Detect In DrawDown Positions ...
|
||||
|
||||
//
|
||||
XPosition positions[];
|
||||
int positionsCount = mTrader.GetInDrawdownPositions(
|
||||
positions);
|
||||
if (!IsValidSize(positionsCount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XPositionTrackerState state;
|
||||
int synced = mPositionTracker.Sync(
|
||||
state,
|
||||
mTrader //
|
||||
);
|
||||
if (synced > 0)
|
||||
// Create a HashMap for Holding Positions ...
|
||||
CHashMap<string, XSCPositionHolder *> symbolMap;
|
||||
|
||||
//
|
||||
// Loop Through Positions ...
|
||||
for (int i = 0; i < positionsCount; i++)
|
||||
{
|
||||
//
|
||||
// Check State and Do What we Want ...
|
||||
int onProfitsCount = ArraySize(state.onProfits);
|
||||
int onDrawdownCount = ArraySize(state.onDrawdowns);
|
||||
XPosition iPosition = positions[i];
|
||||
|
||||
//
|
||||
// Do What we want whe a Position Dropped to Prefit ...
|
||||
if (onProfitsCount > 0)
|
||||
bool hasIKey = symbolMap.ContainsKey(iPosition.symbol);
|
||||
|
||||
//
|
||||
// Empty Class Pointer ...
|
||||
XSCPositionHolder *mHolder = NULL;
|
||||
|
||||
//
|
||||
// Add new to Map ...
|
||||
if (!hasIKey)
|
||||
{
|
||||
//
|
||||
for (int i = 0; i < onProfitsCount; i++)
|
||||
mHolder = new XSCPositionHolder();
|
||||
if (symbolMap.TrySetValue(iPosition.symbol, mHolder))
|
||||
{
|
||||
//
|
||||
XPositionTrack iTrack = state.onProfits[i];
|
||||
|
||||
//
|
||||
string message = "Position (" + ToString(iTrack.ticket) + ", " + iTrack.symbol + ") Dropped in Profit ...";
|
||||
mAlert.Alert(message);
|
||||
mHolder.AddOrUpdateItem(iPosition);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Update Exists in Map ...
|
||||
else
|
||||
{
|
||||
//
|
||||
if (symbolMap.TryGetValue(iPosition.symbol, mHolder))
|
||||
{
|
||||
mHolder.AddOrUpdateItem(iPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now we Have a Map which Filled Based on Separate Symbols and InDrawDown Positions ...
|
||||
int mapCount = symbolMap.Count();
|
||||
if (!IsValidSize(mapCount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
string mSymbols[];
|
||||
XSCPositionHolder *mHolders[];
|
||||
mapCount = symbolMap.CopyTo(
|
||||
mSymbols,
|
||||
mHolders //
|
||||
);
|
||||
if (!IsValidSize(mapCount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < mapCount; i++)
|
||||
{
|
||||
//
|
||||
string iSymbol = mSymbols[i];
|
||||
XSCPositionHolder *iHolder = mHolders[i];
|
||||
|
||||
//
|
||||
XPosition iMaxInDP;
|
||||
bool hasMaxInDP = iHolder.GetMaxInDrawdown(iMaxInDP);
|
||||
if (!hasMaxInDP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Do what we want when a Position Dropped to Drawdown ...
|
||||
if (onDrawdownCount > 0)
|
||||
{
|
||||
//
|
||||
for (int i = 0; i < onDrawdownCount; i++)
|
||||
{
|
||||
//
|
||||
XPositionTrack iTrack = state.onDrawdowns[i];
|
||||
|
||||
//
|
||||
string message = "Position (" + ToString(iTrack.ticket) + ", " + iTrack.symbol + ") Dropped in Drawdown ...";
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
}
|
||||
// Try to Protect a Position ...
|
||||
ProtectPosition(iMaxInDP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,6 +1615,21 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Protect Specified Position ...
|
||||
void ProtectPosition(XPosition &position)
|
||||
{
|
||||
//
|
||||
// Here i Can Protect Position ...
|
||||
|
||||
//
|
||||
string message = "For (" + position.symbol + ") Max In Drawdown Position is: (" +
|
||||
ToString(position.ticket) + "), by Profit: " + ToString(position.profit);
|
||||
|
||||
//
|
||||
mAlert.Alert(message);
|
||||
}
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user