This commit is contained in:
2024-05-25 08:43:32 +03:30
parent da63c4cb71
commit b8515c9d05
5 changed files with 1307 additions and 374 deletions
+533 -3
View File
@@ -29,12 +29,180 @@
// Define On Signal Event Handler Type ...
typedef void (*TOnSignal)(XSignal &signals[]);
//
enum ENUM_X_PROFIT_TRACK_FIELDS
{
X_PROFIT_TRACK_PROFIT,
X_PROFIT_TRACK_LONGS_PROFIT,
X_PROFIT_TRACK_SHORTS_PROFIT,
};
//
// Model Account Profits ...
struct XProfitTracker {
struct XProfitTrack
{
//
int longs; // Number of Long ...
int shorts; // Number of Short ...
//
double profit; // Profit of All ...
double longsProfit; // Profits of Longs ...
double shortsProfit; // Profits of Shorts ...
//
double profitFrom; // Profit of All ...
double longsProfitFrom; // Profits of Longs ...
double shortsProfitFrom; // Profits of Shorts ...
//
double volume; // Volume ...
double longsVolume; // Volume of Longs ...
double shortsVolume; // Volume of Shorts ...
//
datetime time; // Check Time ...
//
XProfitTrack()
{
Clean();
}
//
// Tools ...
//
// Initialization ...
bool Init(XSCTrade *mTrader)
{
//
bool result = false;
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
result = positionsCount > 0;
if (!result)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
bool isLong = IsLong(iPosition.type);
//
if (isLong)
{
//
longs++;
longsVolume += iPosition.volume;
longsProfit += iPosition.profit;
}
else
{
//
shorts++;
shortsVolume += iPosition.volume;
shortsProfit += iPosition.profit;
}
//
profit += iPosition.profit;
volume += iPosition.volume;
}
//
result = IsValid();
if (result)
{
time = TimeCurrent();
}
//
return result;
}
//
double SelectField(ENUM_X_PROFIT_TRACK_FIELDS field)
{
//
double result = profit;
//
switch (field)
{
//
case X_PROFIT_TRACK_LONGS_PROFIT:
result = longsProfit;
break;
//
case X_PROFIT_TRACK_SHORTS_PROFIT:
result = shortsProfit;
break;
//
default:
case X_PROFIT_TRACK_PROFIT:
result = profit;
break;
}
//
return result;
}
//
// Cleanup ...
void Clean()
{
//
longs = 0;
shorts = 0;
profit = 0;
volume = 0;
profitFrom = 0;
longsVolume = 0;
longsProfit = 0;
shortsVolume = 0;
shortsProfit = 0;
longsProfitFrom = 0;
shortsProfitFrom = 0;
//
time = NULL;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
(longs > 0 || shorts > 0)
//
&&
//
volume > 0
//
;
//
return result;
}
//
int count; // Number of Positions ...
};
//
@@ -401,6 +569,9 @@ public:
// Check Trade Events ...
OnTrade();
//
HandleProfitManageMent();
//
// First Check For Any Guard Actions ...
// then Handle Guards if Provided ...
@@ -698,6 +869,16 @@ public:
}
}
//
virtual void OnGoingToProfit(XProfitTrack &track) {}
virtual void OnLongsGoingToProfit(XProfitTrack &track) {}
virtual void OnShortsGoingToProfit(XProfitTrack &track) {}
//
virtual void OnGoingToDrawdown(XProfitTrack &track) {}
virtual void OnLongsGoingToDrawdown(XProfitTrack &track) {}
virtual void OnShortsGoingToDrawdown(XProfitTrack &track) {}
//
// Protected ...
protected:
@@ -815,6 +996,355 @@ protected:
return result;
}
//
// Profit Tracker ...
//
XProfitTrack mProfitTracks[];
//
bool GetProfitTrack(
XProfitTrack &track,
int index = 0 //
)
{
//
bool result = false;
//
if (index < 0)
{
index = 0;
}
//
int tracksCount = CountProfitTracks();
result = tracksCount > 0 && index < tracksCount;
if (!result)
{
return result;
}
//
track.Clean();
//
track = mProfitTracks[index];
//
result = track.IsValid();
//
return result;
}
//
int CountProfitTracks()
{
return ArraySize(mProfitTracks);
}
//
void AddProfitTrack()
{
//
XProfitTrack track;
bool isValid = track.Init(mTrader);
if (!isValid)
{
return;
}
//
ArraySetAsSeries(mProfitTracks, false);
//
AddRef(
track,
mProfitTracks //
);
//
ArraySetAsSeries(mProfitTracks, true);
}
//
// Extract Specified Field Vales of XProfit Track Struct ...
int ExtractProfitTrackField(
double &result[],
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
Clean(result);
//
if (start < 0)
{
start = 0;
}
//
int end = start + count;
//
int tracksCount = CountProfitTracks();
if (end > tracksCount)
{
end = tracksCount;
}
//
for (int i = start; i < end; i++)
{
//
XProfitTrack iTrack;
bool isValid = GetProfitTrack(
iTrack,
i //
);
//
if (!isValid)
{
continue;
}
//
double iValue = iTrack.SelectField(field);
Add(
iValue,
result //
);
}
//
int mResult = ArraySize(result);
//
return mResult;
}
//
double AverageProfitTrackField(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
double result = EMPTY_VALUE;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
result = GetAverage(items);
//
return result;
}
//
bool IsProfitTrackFieldIncreasing(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
bool result = false;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
int from = itemsCount - 1;
int to = 0;
//
result = IsIncreasing(
from,
to,
items //
);
//
return result;
}
//
bool IsProfitTrackFieldDecreasing(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
bool result = false;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
int from = itemsCount - 1;
int to = 0;
//
result = IsDecreasing(
from,
to,
items //
);
//
return result;
}
//
void HandleProfitManageMent()
{
//
AddProfitTrack();
//
int profitsCount = CountProfitTracks();
if (profitsCount <= 1)
{
return;
}
//
XProfitTrack cT;
bool isValid = GetProfitTrack(
cT,
0 //
);
if (!isValid)
{
return;
}
//
XProfitTrack pT;
isValid = GetProfitTrack(
pT,
1 //
);
if (!isValid)
{
return;
}
//
cT.profitFrom = pT.profit;
cT.longsProfitFrom = pT.longsProfit;
cT.shortsProfitFrom = pT.shortsProfit;
//
bool isGoningToProfit =
//
cT.profit > 0 &&
pT.profit <= 0
//
;
if (isGoningToProfit)
{
//
OnGoingToProfit(cT);
}
//
bool isLongsGoningToProfit =
//
cT.longsProfit > 0 &&
pT.longsProfit <= 0
//
;
if (isLongsGoningToProfit)
{
OnLongsGoingToProfit(cT);
}
//
bool isShortsGoningToProfit =
//
cT.shortsProfit > 0 &&
pT.shortsProfit <= 0
//
;
if (isShortsGoningToProfit)
{
OnShortsGoingToProfit(cT);
}
//
bool isGoningToDrawdown =
//
cT.profit < 0 &&
pT.profit >= 0
//
;
if (isGoningToDrawdown)
{
OnGoingToDrawdown(cT);
}
bool isLongsGoningToDrawdown =
//
cT.longsProfit < 0 &&
pT.longsProfit >= 0
//
;
if (isLongsGoningToDrawdown)
{
OnLongsGoingToDrawdown(cT);
}
bool isShortsGoningToDrawdown =
//
cT.shortsProfit < 0 &&
pT.shortsProfit >= 0
//
;
if (isShortsGoningToDrawdown)
{
OnShortsGoingToDrawdown(cT);
}
}
//
// Guards ...