This commit is contained in:
2024-07-28 14:16:13 +03:30
parent 0e3df1a494
commit be741a0ebd
3 changed files with 383 additions and 50 deletions
+367 -39
View File
@@ -4464,6 +4464,8 @@ public:
//
item.recoveryTPPoint = mRecoveryTPPoint;
item.recoverySLPoint = mRecoverySLPoint;
item.maxAllowedRecover = mMaxAllowedRecover;
item.recoveryVolumeMultiplier = mRecoveryVolumeMultiplier;
}
//
@@ -4685,8 +4687,6 @@ public:
}
}
//
//
// Do Force Closing ...
@@ -4699,15 +4699,18 @@ public:
double profit = mData[i].profit;
double volume = mData[i].volume;
string symbol = mData[i].symbol;
string provider = mData[i].provider;
bool isLong = IsLong(mData[i].type);
ENUM_TIMEFRAMES period = mData[i].period;
double points = GetPoints(mData[i].symbol);
bool ignoreTPOnTrail = mData[i].ignoreTPOnTrail;
double recoveryTPPoint = mData[i].recoveryTPPoint;
double recoverySLPoint = mData[i].recoverySLPoint;
int maxAllowedRecover = mData[i].maxAllowedRecover;
double trailStepInPoints = mData[i].trailStepInPoint;
double trailStartInPoint = mData[i].trailStartInPoint;
bool trailBasedOnProfit = mData[i].trailBasedOnProfit;
double recoveryTPPoint = mData[i].recoveryTPPoint;
double recoverySLPoint = mData[i].recoverySLPoint;
double recoveryVolumeMultiplier = mData[i].recoveryVolumeMultiplier;
//
XPosition iPosition;
@@ -4731,6 +4734,132 @@ public:
continue;
}
//
// Handle Recovery Break Event ...
if (mData[i].allowRecover)
{
//
if (mData[i].recoveryLevel <= 0)
{
//
if (profit > 0)
{
//
double proftiInPoints = profit / volume;
bool canClose = proftiInPoints >= recoveryTPPoint;
if (canClose)
{
//
string comment = "Recovery TP ...";
bool isClosed = mTrader.Close(
ticket,
comment //
);
if (isClosed)
{
//
string msg = "Position (" + ToString(ticket) + ") Hit's Recovery TP ...";
Alert(msg);
break;
}
}
}
}
else
{
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(
positions,
symbol,
provider,
period //
);
if (positionsCount > 0)
{
//
XPosition recoveries[];
int recoveriesCount = ExtractRecoveries(
ticket,
positions,
recoveries //
);
//
if (recoveriesCount > 0)
{
//
XPosition mustClose[];
AddRef(
iPosition,
mustClose //
);
//
double requiredProfitPoints = (mData[i].recoveryLevel + 1) * recoveryTPPoint;
//
double rSwap = mData[i].swap;
double rVolume = volume;
double rProfit = profit;
double rCommission = mData[i].commission;
for (int i = 0; i < recoveriesCount; i++)
{
//
rSwap += recoveries[i].swap;
rProfit += recoveries[i].profit;
rVolume += recoveries[i].volume;
rCommission += mTrader.GetPositionCommission(recoveries[i].ticket);
//
AddRef(
recoveries[i],
mustClose //
);
}
//
double profitSummary =
rProfit + (-1 * rSwap) - MathAbs(rCommission);
if (profitSummary > 0)
{
//
double rProfitInPoints = profitSummary / volume;
//
bool canFinishRecovery = rProfitInPoints >= requiredProfitPoints;
if (canFinishRecovery)
{
//
// Here we Have to close All Recoveries
// and Position it Self ...
//
string comment = "Recovery Done ...";
//
int closeds = mTrader.Close(
mustClose,
comment //
);
if (closeds > 0)
{
//
string msg = "EQM Done Recovery (" + ToString(closeds) + ") Positions ...";
Alert(msg);
}
}
//
Clean(mustClose);
Clean(positions);
Clean(recoveries);
}
}
}
}
}
//
// Retriece CIndex Bar ...
XOHCL cBar;
@@ -4762,6 +4891,14 @@ public:
tmpLSW,
true //
);
bool isBullishSigns =
//
isBullishTrend &&
hasBullishPower &&
hasBullishPattern &&
hasBullishPressure
//
;
//
// Bearish ...
@@ -4771,8 +4908,16 @@ public:
bool isBearishTrend = cBar.HasBearishTrend(
tmpHSW,
tmpLSW,
false //
true //
);
bool isBearishSigns =
//
isBearishTrend &&
hasBearishPower &&
hasBearishPattern &&
hasBearishPressure
//
;
//
// Trail ...
@@ -4954,65 +5099,228 @@ public:
//
// Profit Must be Negative ...
if (
profit < 0 &&
recoveryTPPoint > 0 &&
recoverySLPoint > 0)
recoverySLPoint > 0 &&
mData[i].recoveryLevel < maxAllowedRecover)
{
//
// Current Profit ...
double drawdownInPoints = (MathAbs(profit) / volume);
double distanceInPoints = (MathAbs(profit) / volume);
double _volume = volume * ((mData[i].recoveryLevel + 1) * recoveryVolumeMultiplier);
string _comment = GenerateRecoveryTag(ticket);
//
// Try to Remove SL of Recovery Signals ...
if (iPosition.sl > 0)
if (iPosition.sl > 0 || iPosition.tp > 0)
{
//
string comment = "EQM Recover Remove SL";
string comment = "EQM Recover Remove TP/SL";
bool isSLRemoved = mTrader.Modify(
ticket,
0,
iPosition.tp,
0,
comment //
);
}
else
//
if (profit < 0)
{
//
// Check Position TP ...
double rewardInPoints = iPosition.GetReward() / points;
if (rewardInPoints != recoveryTPPoint)
if (mRecoverBasedOnPressures)
{
//
double reward = recoveryTPPoint * points;
double tp =
isLong
? iPosition.entry + reward
: iPosition.entry - reward;
string comment = "EQM Recover Fix TP";
bool isSLRemoved = mTrader.Modify(
ticket,
iPosition.sl,
tp,
comment //
);
bool canRecover = distanceInPoints >= recoverySLPoint * 0.75;
if (canRecover)
{
//
XSignal rSignal;
bool isPrepared = false;
double longEntry = GetEntry(symbol, POSITION_TYPE_BUY);
double shortEntry = GetEntry(symbol, POSITION_TYPE_SELL);
//
if (isBullishSigns)
{
//
rSignal.Clean();
isPrepared = rSignal.Prepare(
symbol,
provider,
period,
POSITION_TYPE_BUY,
X_ORDER_MODE_MARKET,
longEntry,
_volume,
0,
0 //
);
}
else if (isBearishSigns)
{
//
rSignal.Clean();
isPrepared = rSignal.Prepare(
symbol,
provider,
period,
POSITION_TYPE_SELL,
X_ORDER_MODE_MARKET,
shortEntry,
_volume,
0,
0 //
);
}
//
if (isPrepared)
{
//
rSignal.comment = _comment;
//
bool isExecuted = ExecuteRecoverySignal(rSignal);
if (isExecuted)
{
mData[i].recoveryLevel++;
}
}
}
}
else
{
//
// Check Price Distance For Recovery ...
bool canLookForPressure =
//
// in 75% ...
drawdownInPoints > ((recoverySLPoint / 3) * 2)
//
;
//
if (canLookForPressure)
bool canRecover = distanceInPoints >= recoverySLPoint;
if (canRecover)
{
//
// Looking for Signal Direction and
// Founding Pressure ...
ENUM_POSITION_TYPE _type =
isLong
? POSITION_TYPE_SELL
: POSITION_TYPE_BUY;
double _entry = GetEntry(symbol, _type);
//
XSignal rSignal;
bool isPrepared = rSignal.Prepare(
symbol,
provider,
period,
_type,
X_ORDER_MODE_MARKET,
_entry,
_volume,
0,
0 //
);
if (isPrepared)
{
//
rSignal.comment = _comment;
//
bool isExecuted = ExecuteRecoverySignal(rSignal);
if (isExecuted)
{
mData[i].recoveryLevel++;
}
}
}
}
}
else if (profit >= 0 && mData[i].recoveryLevel > 0)
{
//
if (mRecoverBasedOnPressures)
{
//
XSignal rSignal;
bool isPrepared = false;
double longEntry = GetEntry(symbol, POSITION_TYPE_BUY);
double shortEntry = GetEntry(symbol, POSITION_TYPE_SELL);
//
if (isBullishSigns)
{
//
rSignal.Clean();
isPrepared = rSignal.Prepare(
symbol,
provider,
period,
POSITION_TYPE_BUY,
X_ORDER_MODE_MARKET,
longEntry,
_volume,
0,
0 //
);
}
else if (isBearishSigns)
{
//
rSignal.Clean();
isPrepared = rSignal.Prepare(
symbol,
provider,
period,
POSITION_TYPE_SELL,
X_ORDER_MODE_MARKET,
shortEntry,
_volume,
0,
0 //
);
}
//
if (isPrepared)
{
//
rSignal.comment = _comment;
//
bool isExecuted = ExecuteRecoverySignal(rSignal);
if (isExecuted)
{
mData[i].recoveryLevel++;
}
}
}
else
{
//
ENUM_POSITION_TYPE _type =
isLong
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
double _entry = GetEntry(symbol, _type);
//
XSignal rSignal;
bool isPrepared = rSignal.Prepare(
symbol,
provider,
period,
_type,
X_ORDER_MODE_MARKET,
_entry,
_volume,
0,
0 //
);
if (isPrepared)
{
//
rSignal.comment = _comment;
//
bool isExecuted = ExecuteRecoverySignal(rSignal);
if (isExecuted)
{
mData[i].recoveryLevel++;
}
}
}
}
@@ -5342,6 +5650,26 @@ private:
requiredProfitsForHedge -= commissions;
}
//
bool ExecuteRecoverySignal(XSignal &signal)
{
//
bool result = false;
//
ENUM_X_SIGNAL_EXECUTION_RESULT state;
result = mTrader.ExecuteSignal(
signal,
state,
ORDER_TIME_GTC,
NULL,
false //
);
//
return result;
}
//
};
+4 -4
View File
@@ -43,8 +43,8 @@ double eaAllowLong = true; // Allow Long Positions
double eaAllowShort = true; // Allow Short Positions
//
int eaMaxAllowedLongs = 0; // Max Allowed Long Positions
int eaMaxAllowedShorts = 0; // Max Allowed Short Positions
int eaMaxAllowedLongs = 1; // Max Allowed Long Positions
int eaMaxAllowedShorts = 1; // Max Allowed Short Positions
//
double eaTPPoint = 100; // Static TP Point
@@ -113,8 +113,8 @@ int OnInit()
drawPrefix = ShortName;
//
EventSetTimer(5);
// EventSetMillisecondTimer(100);
// EventSetTimer(1);
EventSetMillisecondTimer(100);
//
// Init Succeed ...
+12 -7
View File
@@ -3507,7 +3507,7 @@ struct XTradeData
(maxDrawdown == 0 ||
MathAbs(profit) > MathAbs(maxDrawdown)))
{
profit = maxDrawdown;
maxDrawdown = profit;
}
//
@@ -3785,18 +3785,22 @@ struct XTradeData
// Recovery ...
//
bool allowRecover; // Allow Recover Specified Position
double recoveryTPPoint; // Recovery TP Point
double recoverySLPoint; // Recovery SL Point
int maxAllowedRecover; // Max Allowed Recovery
bool allowRecover; // Allow Recover Specified Position
double recoveryTPPoint; // Recovery TP Point
double recoverySLPoint; // Recovery SL Point
int maxAllowedRecover; // Max Allowed Recovery
int recoveryLevel; // Number of Recovery Signals
double recoveryVolumeMultiplier; // Recovery Volume Multiplier
//
void ResetRecovery()
{
//
allowRecover = false;
recoveryLevel = 0;
recoveryTPPoint = 0;
recoverySLPoint = 0;
recoveryVolumeMultiplier = 0;
}
//
@@ -5418,8 +5422,9 @@ int ExtractRecoveries(
XPosition iSource = source[i];
//
ulong isRecovery = ExtractRecoveredTicket(iSource.comment) > 0;
if (isRecovery && iSource.ticket == ticket)
ulong parentTicket = ExtractRecoveredTicket(iSource.comment);
bool isRecovery = parentTicket > 0;
if (isRecovery && parentTicket == ticket)
{
//
AddRef(