This commit is contained in:
2024-06-26 18:04:28 +03:30
parent 2e365b2bc2
commit f048bd3d37
4 changed files with 814 additions and 165 deletions
+296 -128
View File
@@ -298,7 +298,29 @@ struct XTradeInfo
} }
// //
string ToString() string GetSignalFileName()
{
//
string result = NULL;
//
result =
//
symbol + "\\" +
ToString(type) + "\\" +
provider + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
string ToString(
bool onlySignals = false //
)
{ {
// //
string result = NULL; string result = NULL;
@@ -346,7 +368,9 @@ struct XTradeInfo
// //
result = result =
// //
ToString("Ticket", ticket) + (onlySignals
? ""
: ToString("Ticket", ticket)) +
ToString("Symbol", symbol) + ToString("Symbol", symbol) +
ToString("Period", period) + ToString("Period", period) +
ToString("Entry", entry) + ToString("Entry", entry) +
@@ -354,14 +378,16 @@ struct XTradeInfo
ToString("Type", ToString(type)) + ToString("Type", ToString(type)) +
ToString("Time", time) + ToString("Time", time) +
ToString("Pushers", pushers) + ToString("Pushers", pushers) +
"-------------" + "\n" + (onlySignals
? ""
: "-------------" + "\n" +
ToString("Volume", volume) + ToString("Volume", volume) +
ToString("Profit", profit) + ToString("Profit", profit) +
ToString("Commission", commission) + ToString("Commission", commission) +
ToString("Swap", swap) + ToString("Swap", swap) +
ToString("End Time", endTime) + ToString("End Time", endTime) +
ToString("Age", age) + ToString("Age", age) +
ToString("Message", message) + ToString("Message", message)) +
"-------------" + "\n" + "-------------" + "\n" +
"Conditions" + "\n" + "Conditions" + "\n" +
"-------------" + "\n" + "-------------" + "\n" +
@@ -932,6 +958,37 @@ public:
return result; return result;
} }
//
bool SaveSignal(XTradeInfo &item)
{
//
bool result = false;
//
string content = item.ToString();
result = IsValid(content);
if (!result)
{
return result;
}
//
int mHandler = GetSignalFileHandlerForWrite(item);
result = mHandler != INVALID_HANDLE;
if (!result)
{
return result;
}
//
FileWrite(mHandler, content);
FileFlush(mHandler);
FileClose(mHandler);
//
return result;
}
// //
// Protected ... // Protected ...
protected: protected:
@@ -964,7 +1021,32 @@ private:
// //
result = result =
// //
mPath + "\\" + fileName + ".x121.log" mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log"
//
;
//
return result;
}
//
string GetSignalFilePath(XTradeInfo &item)
{
//
string fileName = item.GetSignalFileName();
//
return GetSignalFilePath(fileName);
}
string GetSignalFilePath(string fileName)
{
//
string result = "";
//
result =
//
mPath + "\\" + "Signals" + "\\" + fileName + ".x121.log"
// //
; ;
@@ -1015,6 +1097,50 @@ private:
// //
return result; return result;
} }
//
int GetSignalFileHandlerForRead(XTradeInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetSignalFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_TXT //
);
//
return result;
}
int GetSignalFileHandlerForWrite(XTradeInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetSignalFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_WRITE | FILE_TXT //
);
//
return result;
}
}; };
// //
@@ -1063,6 +1189,65 @@ public:
mSave = value; mSave = value;
} }
//
bool GetSaveSignalsOnly()
{
return mSaveSignalsOnly;
}
//
void SetSaveSignalsOnly(bool value)
{
mSaveSignalsOnly = value;
}
//
// Hedging ...
//
double MinProfitPerTrade()
{
return mMinProfitPerTrade;
}
//
void MinProfitPerTrade(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinProfitPerTrade = value;
}
//
double MinProfitPerVolumeFactor()
{
return mMinProfitPerVolumeFactor;
}
//
void MinProfitPerVolumeFactor(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 0 && value < 0.01)
{
value = 0.01;
}
//
mMinProfitPerVolumeFactor = value;
}
// //
// Trailling Stop ... // Trailling Stop ...
@@ -1684,6 +1869,12 @@ public:
info, info,
data // data //
); );
//
if (GetSaveSignalsOnly())
{
collector.SaveSignal(info);
}
} }
// //
@@ -2163,6 +2354,12 @@ protected:
// //
bool mSave; // Save Results ... bool mSave; // Save Results ...
bool mSaveSignalsOnly; // Save Only Signals and COnditions
//
// Hedging ...
double mMinProfitPerTrade; // Minimum Required Profit for Hedging
double mMinProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Volume
// //
// Trailling ... // Trailling ...
@@ -3497,6 +3694,18 @@ public:
mTradeHandler.SetSave(value); mTradeHandler.SetSave(value);
} }
//
bool SaveSignalsOnly()
{
return mTradeHandler.GetSaveSignalsOnly();
}
//
void SaveSignalsOnly(bool value)
{
mTradeHandler.SetSaveSignalsOnly(value);
}
// //
double MinFreeMargingForOpenTrades() double MinFreeMargingForOpenTrades()
{ {
@@ -3516,6 +3725,37 @@ public:
mMinFreeMargingForOpenTrades = value; mMinFreeMargingForOpenTrades = value;
} }
//
// Hedging ...
//
double MinProfitPerTrade()
{
return mTradeHandler.MinProfitPerTrade();
}
//
void MinProfitPerTrade(double value)
{
//
MinRequiredProfitPerTrade(value);
mTradeHandler.MinProfitPerTrade(value);
}
//
double MinProfitPerVolumeFactor()
{
return mTradeHandler.MinProfitPerVolumeFactor();
}
//
void MinProfitPerVolumeFactor(double value)
{
//
MinRequiredProfitPerVolumeFactor(value);
mTradeHandler.MinProfitPerVolumeFactor(value);
}
// //
// Overrides ... // Overrides ...
@@ -4384,7 +4624,7 @@ public:
bool HandleStateManagement(XSignal &signals[]) override bool HandleStateManagement(XSignal &signals[]) override
{ {
// //
const bool result = false; bool result = false;
// //
// Do all State Management here ... // Do all State Management here ...
@@ -4395,7 +4635,11 @@ public:
// Youngest Age of Positions longest as enough // Youngest Age of Positions longest as enough
// Make State of Signalling to Force State for Recieving // Make State of Signalling to Force State for Recieving
// Signal and Clear their Tp and SL for allowing hedges ... // Signal and Clear their Tp and SL for allowing hedges ...
EQMHandleForceState(); EQMHandleForceState(signals);
if (mForce)
{
result = true;
}
// //
DoHedge(); DoHedge();
@@ -4582,6 +4826,9 @@ protected:
// //
Alert(message); Alert(message);
//
EQMHandleForceState(signals);
// //
return; return;
} }
@@ -4843,6 +5090,7 @@ private:
// //
SaveResults(false); SaveResults(false);
SaveSignalsOnly(true);
} }
// //
@@ -4990,7 +5238,8 @@ private:
XSignal supports[]; XSignal supports[];
int supportsCount = mTradeHandler.DoProtect( int supportsCount = mTradeHandler.DoProtect(
supports, supports,
mSetups); mSetups //
);
// //
if (IsValidSize(supportsCount)) if (IsValidSize(supportsCount))
@@ -5038,146 +5287,65 @@ private:
// //
// Handle Force State Management ... // Handle Force State Management ...
void EQMHandleForceState() bool mForce;
void EQMHandleForceState(XSignal &forceSignals[])
{ {
// //
// Validate Force Marigin ...
double marigin = mTrader.mAccount.GetMargin();
double minFreeMarigin = MinFreeMargingForOpenTrades();
double forceMargin = 3 * minFreeMarigin; // TODO: Make It Configurable
//
// Retrieving Positions ...
XPosition positions[]; XPosition positions[];
int positionsCount = mTrader.GetPositions(positions); int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount) || positionsCount <= 4) if (!IsValidSize(positionsCount))
{ {
return; return;
} }
// //
double minRequiredProfitPerTrade = MinRequiredProfitPerTrade(); XPosition oldest;
double minRequiredProfitPerVolumeFactor = MinRequiredProfitPerVolumeFactor(); int oldestAge = GetOldest(
oldest,
positions //
);
//
mForce = marigin >= forceMargin && oldestAge >= 288;
if (!mForce)
{
return;
}
//
double minProfitPerTrade = MinProfitPerTrade();
double minProfitPerVolumeFactor = MinProfitPerVolumeFactor();
// //
double profit = SpecifiedCalculatePositionsProfit(positions); double profit = SpecifiedCalculatePositionsProfit(positions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
positions, positions,
minRequiredProfitPerTrade, minProfitPerTrade,
minRequiredProfitPerVolumeFactor // minProfitPerVolumeFactor //
); );
// //
bool canClose = XSymbolPositions symbolPositions[];
profit > 0 && int symbolPositionsCount = ExtractSymbolPositions(
(profit == requiredProfit || positions,
profit >= requiredProfit / 2); symbolPositions,
if (canClose) { minProfitPerTrade,
DoEQMForceClose(); minProfitPerVolumeFactor //
);
if (!IsValidSize(symbolPositionsCount))
{
return;
} }
return;
// //
// XPosition positions[];
// int positionsCount = mTrader.GetPositions(positions);
// if (!IsValidSize(positionsCount))
// {
// //
// EQMClearAllForceStates();
// //
// return;
// }
// //
// // Search For Force State Per Each Setup ...
// //
// int forceCount = 0;
// int setupsCount = CountSetups();
// if (IsValidSize(setupsCount))
// {
// //
// int maxAllowed = MaxAllowedTrades();
// bool perDirection = UseMaxAllowedPerDirection();
// //
// for (int i = 0; i < setupsCount; i++)
// {
// //
// string iSymbol = mSetups[i].GetSymbol();
// ENUM_TIMEFRAMES iPeriod = mSetups[i].GetPeriod();
// //
// XPosition iPositions[];
// int iPositionsCount = mTrader.GetPositions(
// iPositions,
// iSymbol,
// NULL, // All Providers ...
// NULL, // All Periods ...
// NULL, // All Types ...
// true // Filter By Magic ...
// );
// if (!IsValidSize(iPositionsCount))
// {
// continue;
// }
// //
// // Counting Positions ...
// int longs;
// double longProfits;
// double longVolumes;
// //
// int shorts;
// double shortProfits;
// double shortVolumes;
// //
// CountPositions(
// iPositions,
// //
// longs,
// longProfits,
// longVolumes,
// //
// shorts,
// shortProfits,
// shortVolumes //
// );
// //
// bool isMaxReached =
// maxAllowed <= 0
// ? false
// : !perDirection
// ? longs + shorts >= maxAllowed
// : longs >= maxAllowed && shorts >= maxAllowed;
// double volumeSummary = longVolumes + shortVolumes;
// double profitsSummary = longProfits + shortProfits;
// //
// bool isIInForce =
// //
// maxAllowed <= 0
// ? profitsSummary < 0 &&
// longVolumes == shortVolumes
// : isMaxReached &&
// profitsSummary < 0 &&
// longVolumes == shortVolumes
// //
// ;
// if (isIInForce)
// {
// //
// forceCount++;
// mSetups[i].ForceState(true);
// }
// }
// }
// //
// bool isForce = forceCount >= 1;
// if (!isForce)
// {
// return;
// }
// //
Log("symbolPositionsCount: " + ToString(symbolPositionsCount));
} }
// //
+206
View File
@@ -4866,3 +4866,209 @@ int pivotsCount = ArraySize(pivots);
} }
} }
} }
////////////////////////////////////////////////////////////////////////////////////
void EQMHandleForceState()
{
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount) || positionsCount <= 4)
{
return;
}
//
double minRequiredProfitPerTrade = MinRequiredProfitPerTrade();
double minRequiredProfitPerVolumeFactor = MinRequiredProfitPerVolumeFactor();
//
double profit = SpecifiedCalculatePositionsProfit(positions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
positions,
minRequiredProfitPerTrade,
minRequiredProfitPerVolumeFactor //
);
//
bool canClose =
profit > 0 &&
(profit == requiredProfit ||
profit >= requiredProfit / 2);
if (canClose)
{
DoEQMForceClose();
}
return;
// //
// XPosition positions[];
// int positionsCount = mTrader.GetPositions(positions);
// if (!IsValidSize(positionsCount))
// {
// //
// EQMClearAllForceStates();
// //
// return;
// }
// //
// // Search For Force State Per Each Setup ...
// //
// int forceCount = 0;
// int setupsCount = CountSetups();
// if (IsValidSize(setupsCount))
// {
// //
// int maxAllowed = MaxAllowedTrades();
// bool perDirection = UseMaxAllowedPerDirection();
// //
// for (int i = 0; i < setupsCount; i++)
// {
// //
// string iSymbol = mSetups[i].GetSymbol();
// ENUM_TIMEFRAMES iPeriod = mSetups[i].GetPeriod();
// //
// XPosition iPositions[];
// int iPositionsCount = mTrader.GetPositions(
// iPositions,
// iSymbol,
// NULL, // All Providers ...
// NULL, // All Periods ...
// NULL, // All Types ...
// true // Filter By Magic ...
// );
// if (!IsValidSize(iPositionsCount))
// {
// continue;
// }
// //
// // Counting Positions ...
// int longs;
// double longProfits;
// double longVolumes;
// //
// int shorts;
// double shortProfits;
// double shortVolumes;
// //
// CountPositions(
// iPositions,
// //
// longs,
// longProfits,
// longVolumes,
// //
// shorts,
// shortProfits,
// shortVolumes //
// );
// //
// bool isMaxReached =
// maxAllowed <= 0
// ? false
// : !perDirection
// ? longs + shorts >= maxAllowed
// : longs >= maxAllowed && shorts >= maxAllowed;
// double volumeSummary = longVolumes + shortVolumes;
// double profitsSummary = longProfits + shortProfits;
// //
// bool isIInForce =
// //
// maxAllowed <= 0
// ? profitsSummary < 0 &&
// longVolumes == shortVolumes
// : isMaxReached &&
// profitsSummary < 0 &&
// longVolumes == shortVolumes
// //
// ;
// if (isIInForce)
// {
// //
// forceCount++;
// mSetups[i].ForceState(true);
// }
// }
// }
// //
// bool isForce = forceCount >= 1;
// if (!isForce)
// {
// return;
// }
//
}
//
void EQMHandleForceSignals(
XSignal &signals[] //
)
{
//
// Validate Signals Count ...
int signalsCount = ArraySize(signals);
if (!IsValidSize(signalsCount))
{
return;
}
//
// Validate Force Marigin ...
double marigin = mTrader.mAccount.GetMargin();
double forceMargin = 100; // TODO: Make It Configurable
bool isInForceMarigin = marigin >= forceMargin;
if (!isInForceMarigin)
{
return;
}
//
// Now we are Sure we in Force State Margin amd we Have Signals ...
//
// here we Must Symbol Categorized Positions ...
int setupsCount = CountSetups();
if (!IsValidSize(setupsCount))
{
return;
}
//
// Retrieving Positions ...
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount))
{
return;
}
//
XSymbolPositions symbolPositions[];
int symbolPositionsCount = ExtractSymbolPositions(
positions,
symbolPositions //
);
if (!IsValidSize(symbolPositionsCount))
{
return;
}
//
Log("symbolPositionsCount: " + ToString(symbolPositionsCount));
//
}
+6 -6
View File
@@ -44,7 +44,7 @@ input group "Signals";
//,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb //,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb
// EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb // EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb
// EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb,XAUUSDb,NZDUSDb,AUDUSDb,USDCADb,BTCUSD,ETHUSD // EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb,XAUUSDb,NZDUSDb,AUDUSDb,USDCADb,BTCUSD,ETHUSD
input string x121EASymbols = "USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb"; // Symbols input string x121EASymbols = "EURUSDb,USDCHFb,EURCHFb,USDJPYb,EURJPYb,GBPUSDb"; // Symbols
input bool x121EAUseAllSymbols = false; // Use All Available Symbols input bool x121EAUseAllSymbols = false; // Use All Available Symbols
input bool x121EAUseAllWatchListSymbols = false; // Use All WatchList Symbols input bool x121EAUseAllWatchListSymbols = false; // Use All WatchList Symbols
input bool x121EAAllowLong = true; // Allow Long Trades input bool x121EAAllowLong = true; // Allow Long Trades
@@ -60,8 +60,8 @@ input group "Risk Management";
input double x121EAVolume = 0.01; // Static Volume input double x121EAVolume = 0.01; // Static Volume
input double x121EATPPoint = 1000; // TP Point input double x121EATPPoint = 1000; // TP Point
input double x121EASLPoint = 1000; // SL Point input double x121EASLPoint = 1000; // SL Point
input int x121EAMaxAllowedTrades = 2; // Max Allowed Positions Per Symbol input int x121EAMaxAllowedTrades = 0; // Max Allowed Positions Per Symbol
input int x121EAMinFreeMargingForOpenTrades = 500; // Min Margin For Opening Trades input int x121EAMinFreeMargingForOpenTrades = 50; // Min Margin For Opening Trades
input bool x121EAUseMaxAllowedPerDirection = true; // Use Max Allowed Positions Per Direction input bool x121EAUseMaxAllowedPerDirection = true; // Use Max Allowed Positions Per Direction
input bool x121EAIgnoreSL = true; // Ignore Calculated SL input bool x121EAIgnoreSL = true; // Ignore Calculated SL
input bool x121EAIgnoreTP = true; // Ignore Calculated TP input bool x121EAIgnoreTP = true; // Ignore Calculated TP
@@ -377,8 +377,8 @@ bool InitialEA()
// //
// Hedging ... // Hedging ...
x121EA.RestingAfterHedge(x121EARestingAfterHedge); x121EA.RestingAfterHedge(x121EARestingAfterHedge);
x121EA.MinRequiredProfitPerTrade(x121EAMinRequiredProfitPerTrade); x121EA.MinProfitPerTrade(x121EAMinRequiredProfitPerTrade);
x121EA.MinRequiredProfitPerVolumeFactor(x121EAMinRequiredProfitPerVolumeFactor); x121EA.MinProfitPerVolumeFactor(x121EAMinRequiredProfitPerVolumeFactor);
// //
// Alert ... // Alert ...
@@ -438,7 +438,7 @@ void X121PreConfigureStyles(X121SetupInputs &inputs)
// //
// XATSL ... // XATSL ...
inputs.atslInputs.show = true; inputs.atslInputs.show = false;
// //
// XSLN ... // XSLN ...
+275
View File
@@ -2773,6 +2773,161 @@ struct XTrail
} }
}; };
//
struct XSymbolPositions
{
//
string symbol;
//
double profit;
double longsProfit;
double shortsProfit;
//
double volume;
double longsVolume;
double shortsVolume;
//
double requiredProfitForHedge;
//
XPosition longs[];
XPosition shorts[];
XPosition positions[];
//
XSymbolPositions()
{
Clean();
}
//
bool Update(
double mMinProfitPerTrade,
double mMinProfitPerVolumeFactor //
)
{
//
bool result = false;
//
bool hasChild = HasChild();
if (!hasChild)
{
return result;
}
//
// Extract Types ...
ExtractPositions(
positions,
longs,
shorts //
);
//
int numOfLongs = 0;
int numOfShorts = 0;
CountPositions(
positions,
numOfLongs,
longsProfit,
longsVolume,
numOfShorts,
shortsProfit,
shortsVolume //
);
//
profit = longsProfit + shortsProfit;
volume = longsVolume + shortsVolume;
requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge(
positions,
mMinProfitPerTrade,
mMinProfitPerVolumeFactor //
);
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
symbol = NULL;
//
profit = 0;
longsProfit = 0;
shortsProfit = 0;
//
volume = 0;
longsVolume = 0;
shortsVolume = 0;
//
requiredProfitForHedge = 0;
//
Clean(longs);
Clean(shorts);
Clean(positions);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = IsValid(symbol);
//
return result;
}
//
// Has Child ...
bool HasChild()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
int count = Count();
result = IsValidSize(count);
//
return result;
}
//
// Count ...
int Count()
{
return ArraySize(positions);
}
//
};
// //
// TypeDefs ... // TypeDefs ...
@@ -4646,6 +4801,126 @@ void ExtractPositions(
} }
} }
//
int FindSymbolIndex(
string mSymbol,
XSymbolPositions &mItems[] //
)
{
//
int result = -1;
//
if (!IsValid(mSymbol))
{
return result;
}
//
int count = ArraySize(mItems);
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSymbolPositions iItem = mItems[i];
//
if (iItem.symbol == mSymbol)
{
//
result = i;
break;
}
}
//
return result;
}
//
int ExtractSymbolPositions(
XPosition &positions[],
XSymbolPositions &items[], // Holds Result
double mMinProfitPerTrade,
double mMinProfitPerVolumeFactor //
)
{
//
int result = 0;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
Clean(items);
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (!iPosition.IsValid())
{
continue;
}
//
int itemIDX = FindSymbolIndex(
iPosition.symbol,
items //
);
if (!IsValidIndex(itemIDX))
{
//
// Add New One ...
XSymbolPositions item;
item.symbol = iPosition.symbol;
//
AddRef(
item,
items //
);
itemIDX = FindSymbolIndex(iPosition.symbol, items);
}
//
AddRef(
iPosition,
items[itemIDX].positions //
);
}
//
result = ArraySize(items);
if (IsValidSize(result))
{
//
for (int i = 0; i < result; i++)
{
//
items[i].Update(
mMinProfitPerTrade,
mMinProfitPerVolumeFactor //
);
}
}
//
return result;
}
// //
// Custom Drawings ... // Custom Drawings ...
bool DrawTrendState( bool DrawTrendState(