This commit is contained in:
2025-05-30 23:37:27 +03:30
parent 1e002ced49
commit 16c58af75c
9 changed files with 5676 additions and 4503 deletions
+198
View File
@@ -0,0 +1,198 @@
///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCXGuard ...
// Description: Guard Provider Class ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm Guard Provider Class"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5";
//
// Enumeration ...
//
// Guard Actions ...
enum ENUM_X_GUARD_ACTIONS
{
X_GUARD_ACTION_NONE, // Nothing to Do
X_GUARD_ACTION_CLOSE, // Close Specified Position
X_GUARD_ACTION_CLOSE_ALL, // Close All Positions
X_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions
X_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position
X_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position
X_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position
X_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position
X_GUARD_ACTION_HEDGE, // Hedge Specified Positions
};
//
// Definitions ...
//
// Model a Guard Action ...
struct XGuard
{
//
// Props ...
ENUM_X_GUARD_ACTIONS action;
datetime time;
//
string symbol;
string provider;
//
// Specified Position ...
ulong ticket;
//
// Partial Close ...
double volumeMultiplier;
//
// SL Trial ...
double sl;
//
// TP Trial ...
double tp;
//
// Constructor ...
XGuard()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
time = NULL;
action = X_GUARD_ACTION_NONE;
//
symbol = NULL;
provider = NULL;
//
ticket = 0;
//
volumeMultiplier = 0;
//
sl = 0;
tp = 0;
//
ZeroMemory(this);
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(time) &&
IsValid(symbol) &&
IsValid(provider) &&
action != X_GUARD_ACTION_NONE
//
;
if (!result)
{
return result;
}
//
// Validate Model Based On Specified Guard Actions ...
//
return result;
}
};
//
// Extensions ...
//
bool IsValid(ENUM_X_GUARD_ACTIONS item)
{
//
bool result = false;
//
result = item != X_GUARD_ACTION_NONE;
//
return result;
}
/**
* Add Guard to Collection ...
*
* @param guard: XGuard instance ...
* @param guards: XGuard instance Collection ...
*
* @return ( int )
*/
int AddGuard(
XGuard &guard,
XGuard &guards[] //
)
{
//
int result = 0;
//
if (!guard.IsValid())
{
return result;
}
//
AddRef(
guard,
guards //
);
//
result = ArraySize(guards);
//
return result;
}
//
// Implementation ...
File diff suppressed because it is too large Load Diff
+414 -321
View File
@@ -167,22 +167,11 @@ input bool eaSaveLosts = false; // Save Lost Conditions
//
XCAlert *eaAlert;
XCTrade *eaTrade;
XSignal eaSignal;
string eaTag = "";
XCVolume *eaVolume;
XTriggerBlock eaTB;
CArrayObj *eaObjects;
XCPOIDrawer *eaDrawer;
XBarTracker eaBarTraker;
X121XCatbInputs eaInputs;
XTimeTracker eaTimeTracker;
XCX121XCatbHelper *eaHelper;
XCBarAnalyser *eaBarAnalyser;
XTriggerBlockFilters eaFilters;
X121XCatbConditions eaCatbConditions;
XCXCATBEASignaller *eaSignallers[];
XCXCATBEATradeManager *eaTradeManager;
XCATBEAStrategyConditions eaConditions;
XTriggerBlockValidationRules eaValidations;
//
// Event Handlers ...
@@ -230,13 +219,6 @@ void OnDeinit(const int reason)
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
// REASON_CLOSE 9 Terminal closed
//
// eaObjects.Clear();
//
delete eaHelper;
ZeroMemory(eaHelper);
//
delete eaAlert;
ZeroMemory(eaAlert);
@@ -245,29 +227,12 @@ void OnDeinit(const int reason)
delete eaTrade;
ZeroMemory(eaTrade);
//
delete eaDrawer;
ZeroMemory(eaDrawer);
//
delete eaVolume;
ZeroMemory(eaVolume);
//
delete eaBarAnalyser;
ZeroMemory(eaBarAnalyser);
//
eaTB.Clean();
eaSignal.Clean();
eaSignal.Clean();
eaFilters.Clean();
eaBarTraker.Clean();
eaConditions.Clean();
eaConditions.Clean();
eaTimeTracker.Clean();
eaValidations.Clean();
eaCatbConditions.Clean();
//
DestroyTimer();
@@ -278,236 +243,345 @@ void OnDeinit(const int reason)
void OnTick()
{
//
// Handle Tradings ...
bool tradeUsingTriggerBlock = true;
bool tradeUsingMarketConditions1 = true;
//
// Time Report Handling ...
HandleTimeReport();
//
// Handle Position Management / Protections ...
// Position Management / Protections Handling ...
eaTradeManager.Manage();
//
eaTB.Clean();
eaSignal.Clean();
eaConditions.Clean();
eaCatbConditions.Clean();
//
bool has = false;
int barIndex = 0;
int cBarIndex = 0;
//
// Check Bar Processing ...
if (!eaBarTraker.CanProcessBar())
{
return;
}
//
eaHelper.Check(barIndex);
//
// Reading Required Bars ...
XOHCL zBar;
XOHCL cBar;
has = zBar.Init(
_Symbol,
_Period,
barIndex //
);
has =
has &&
zBar.GetPreviousBar(cBar);
// Count Signallers ...
bool has = HasChild(eaSignallers);
if (!has)
{
//
zBar.Clean();
cBar.Clean();
//
return;
}
//
cBarIndex = barIndex + 1;
XGuard guards[];
XCATBEAStrategyConditions conditions[];
//
// Update All Required Buffers ...
eaHelper.Update(cBarIndex);
//
// Check Trigger Block Detected or Not ...
if (tradeUsingTriggerBlock)
int count = ArraySize(eaSignallers);
for (int i = 0; i < count; i++)
{
//
// Trigger Block Detection ...
has = DetectTriggerBlock1(
eaHelper,
eaBarAnalyser,
eaTB,
eaCatbConditions,
eaValidations,
eaFilters,
barIndex,
10 // Loopback ...
// Retrieve indexed Signaller ...
XCXCATBEASignaller *iSignaller = eaSignallers[i];
//
string iSymbol = iSignaller.GetSymbol();
string iProvider = iSignaller.GetProvider();
ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod();
//
// Now we Have to Check Handle Tick Resoult ...
//
// Requirements ...
XGuard iGuards[]; // Hold Provided Guards ...
XPosition iPositions[]; // Retrieve Signaller Positions ...
XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ...
//
// Reading Signaller Positions ...
eaTradeManager.GetPositions(
iPositions,
iSymbol,
iProvider,
iPeriod //
);
//
// Processing Tick for Signaller ...
iSignaller.ProcessTick(
iPositions,
iGuards,
iConditions //
);
//
// Check Results ...
has = HasChild(iGuards);
if (has)
{
//
// Wait for Next Bar for anything ...
eaBarTraker.Waits();
//
// Prepare Target ...
double targets[];
for (int i = 1; i <= eaSignalR2R; i++)
{
//
Add(
(double)i,
targets //
);
}
//
// Calculate SL Additions ...
double iATR = 0;
if (barIndex > 0 &&
barIndex < ArraySize(eaHelper.atrBuffer))
{
iATR = eaHelper.atrBuffer[barIndex];
}
double slAdditional = eaSLAtrMultiplier * iATR;
//
// Preparing Signal ...
has = ToSignal(
eaTB.trigger,
eaTB.signal,
targets,
slAdditional //
);
//
// Draw Trigger Block ...
DrawTriggerBlock(
eaTB,
eaDrawer,
eaObjects,
NULL //
);
//
// Attach Signal ...
eaSignal = eaTB.signal;
//
// Check Signal Type ...
bool isLong = IsLong(eaSignal.type);
//
// Update Entry ...
eaSignal.entry = GetEntry(
eaSignal.symbol,
eaSignal.type //
);
//
// Update Signal Targets ...
UpdateSignalTargets(eaSignal);
//
// Handle Volume Management ...
double iVolume = eaVolume.CalculateVolume(eaSignal);
if (iVolume > X_MIN_VOLUME &&
iVolume != eaSignal.volume)
{
eaSignal.volume = iVolume;
}
//
eaConditions.sl = eaSignal.sl;
eaConditions.tp = eaSignal.tp;
eaConditions.pivot = eaSignal.sl;
eaConditions.time = eaSignal.time;
eaConditions.reward = eaSignalR2R;
eaConditions.point = eaSignal.entry;
eaConditions.entry = eaSignal.entry;
eaConditions.symbol = eaSignal.symbol;
eaConditions.period = eaSignal.period;
eaConditions.setupTime = eaSignal.time;
eaConditions.triggerTime = eaSignal.time;
eaConditions.decisionZone = eaTB.trigger;
eaConditions.provider = eaSignal.provider;
eaConditions.conditions = eaCatbConditions;
eaConditions.type = ToPositionType(eaSignal.type);
eaConditions.dir =
isLong
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
Copy(
eaSignal.targets,
eaConditions.targets //
);
eaSignal.conditions =
eaCatbConditions
.GenerateSummary(
false, // Commons ...
true, // Conditions ...
true, // Scores ...
false // Ignore Falses ...
);
//
// Execute Signal ...
has = eaTradeManager.Execute(
eaSignal,
eaConditions //
iGuards,
guards,
false // Force Clean ...
);
}
//
eaTB.Clean();
// Check Triggered Conditions ...
has = iConditions.IsValid() &&
iConditions.IsSetuped() &&
iConditions.CanTrigger();
if (has)
{
//
AddRef(
iConditions,
conditions //
);
}
//
// Cleanup Resources ...
Clean(iGuards);
Clean(iPositions);
iConditions.Clean();
}
//
// Trade Using Market Conditions ...
if (tradeUsingMarketConditions1)
// Do Actions Based on Provided Info ...
//
// Guards ...
has = HasChild(guards);
if (has)
{
//
XBoxZone signalZone;
X121XCatbConditions conditions;
has = DetectSignalZone(
eaDrawer,
eaHelper,
eaBarAnalyser,
signalZone,
conditions,
barIndex //
);
if (has)
{
//
// Convert Box to Signal ...
}
// Handle Guards Firing ...
}
//
// Triggers ...
has = HasChild(conditions);
if (has)
{
//
// Handle Conditions Triggering ...
}
//
// Cleanup Resources ...
//
zBar.Clean();
cBar.Clean();
eaTB.Clean();
eaSignal.Clean();
eaConditions.Clean();
eaCatbConditions.Clean();
Clean(guards);
Clean(conditions);
// //
// eaTB.Clean();
// eaSignal.Clean();
// eaConditions.Clean();
// eaCatbConditions.Clean();
// //
// bool has = false;
// int barIndex = 0;
// int cBarIndex = 0;
// //
// // Check Bar Processing ...
// if (!eaBarTraker.CanProcessBar())
// {
// return;
// }
// //
// eaHelper.Check(barIndex);
// //
// // Reading Required Bars ...
// XOHCL zBar;
// XOHCL cBar;
// has = zBar.Init(
// _Symbol,
// _Period,
// barIndex //
// );
// has =
// has &&
// zBar.GetPreviousBar(cBar);
// if (!has)
// {
// //
// zBar.Clean();
// cBar.Clean();
// //
// return;
// }
// //
// cBarIndex = barIndex + 1;
// //
// // Update All Required Buffers ...
// eaHelper.Update(cBarIndex);
// //
// // Check Trigger Block Detected or Not ...
// if (tradeUsingTriggerBlock)
// {
// //
// // Trigger Block Detection ...
// has = DetectTriggerBlock1(
// eaHelper,
// eaBarAnalyser,
// eaTB,
// eaCatbConditions,
// eaValidations,
// eaFilters,
// barIndex,
// 10 // Loopback ...
// );
// //
// if (has)
// {
// //
// // Wait for Next Bar for anything ...
// eaBarTraker.Waits();
// //
// // Prepare Target ...
// double targets[];
// for (int i = 1; i <= eaSignalR2R; i++)
// {
// //
// Add(
// (double)i,
// targets //
// );
// }
// //
// // Calculate SL Additions ...
// double iATR = 0;
// if (barIndex > 0 &&
// barIndex < ArraySize(eaHelper.atrBuffer))
// {
// iATR = eaHelper.atrBuffer[barIndex];
// }
// double slAdditional = eaSLAtrMultiplier * iATR;
// //
// // Preparing Signal ...
// has = ToSignal(
// eaTB.trigger,
// eaTB.signal,
// targets,
// slAdditional //
// );
// //
// // Draw Trigger Block ...
// DrawTriggerBlock(
// eaTB,
// eaDrawer,
// eaObjects,
// NULL //
// );
// //
// // Attach Signal ...
// eaSignal = eaTB.signal;
// //
// // Check Signal Type ...
// bool isLong = IsLong(eaSignal.type);
// //
// // Update Entry ...
// eaSignal.entry = GetEntry(
// eaSignal.symbol,
// eaSignal.type //
// );
// //
// // Update Signal Targets ...
// UpdateSignalTargets(eaSignal);
// //
// // Handle Volume Management ...
// double iVolume = eaVolume.CalculateVolume(eaSignal);
// if (iVolume > X_MIN_VOLUME &&
// iVolume != eaSignal.volume)
// {
// eaSignal.volume = iVolume;
// }
// //
// eaConditions.sl = eaSignal.sl;
// eaConditions.tp = eaSignal.tp;
// eaConditions.pivot = eaSignal.sl;
// eaConditions.time = eaSignal.time;
// eaConditions.reward = eaSignalR2R;
// eaConditions.point = eaSignal.entry;
// eaConditions.entry = eaSignal.entry;
// eaConditions.symbol = eaSignal.symbol;
// eaConditions.period = eaSignal.period;
// eaConditions.setupTime = eaSignal.time;
// eaConditions.triggerTime = eaSignal.time;
// eaConditions.decisionZone = eaTB.trigger;
// eaConditions.provider = eaSignal.provider;
// eaConditions.conditions = eaCatbConditions;
// eaConditions.type = ToPositionType(eaSignal.type);
// eaConditions.dir =
// isLong
// ? X_DIRECTION_BULLISH
// : X_DIRECTION_BEARISH;
// Copy(
// eaSignal.targets,
// eaConditions.targets //
// );
// eaSignal.conditions =
// eaCatbConditions
// .GenerateSummary(
// false, // Commons ...
// true, // Conditions ...
// true, // Scores ...
// false // Ignore Falses ...
// );
// //
// // Execute Signal ...
// has = eaTradeManager.Execute(
// eaSignal,
// eaConditions //
// );
// }
// //
// eaTB.Clean();
// }
// //
// // Trade Using Market Conditions ...
// if (tradeUsingMarketConditions1)
// {
// //
// XBoxZone signalZone;
// X121XCatbConditions conditions;
// has = DetectSignalZone(
// eaDrawer,
// eaHelper,
// eaBarAnalyser,
// signalZone,
// conditions,
// barIndex //
// );
// if (has)
// {
// //
// // Convert Box to Signal ...
// }
// }
// //
// // Cleanup Resources ...
// //
// zBar.Clean();
// cBar.Clean();
// eaTB.Clean();
// eaSignal.Clean();
// eaConditions.Clean();
// eaCatbConditions.Clean();
}
//
@@ -735,13 +809,6 @@ bool InitVolume()
*/
void InitRequirements()
{
//
// Initial Bar Tracker ...
eaBarTraker.Init(
_Symbol,
_Period //
);
//
// Preparing Tags ...
eaTag =
@@ -759,40 +826,6 @@ void InitRequirements()
eaAlert.SetEnableAlerts(eaEnableAlerts);
eaAlert.SetTerminalAlerts(eaTerminalAlerts);
//
// Objects ...
eaObjects = new CArrayObj();
//
// Configure XCA ...
eaInputs.Default();
//
// Hide all Visible Buffers ...
eaInputs.Hide();
//
// we Can make Show all requirements here ...
//
eaInputs.showPV = true;
eaInputs.showSar = true;
eaInputs.showTrend = true;
eaInputs.showATRBand = true;
eaInputs.showPVGolden = true;
//
eaHelper = new XCX121XCatbHelper();
bool isInited = eaHelper.Init(
_Symbol,
_Period,
eaInputs //
);
//
eaDrawer = new XCPOIDrawer();
eaBarAnalyser = new XCBarAnalyser();
//
// EA Trade ...
eaTrade = new XCTrade(
@@ -881,7 +914,7 @@ void InitRequirements()
//
// Ignore unused Cases and Extracts only Content ...
string iSessionDescriptorStr = ExtractString(sessions[i]);
isInited = IsValid(iSessionDescriptorStr);
bool isInited = IsValid(iSessionDescriptorStr);
if (isInited)
{
//
@@ -921,65 +954,125 @@ void InitRequirements()
}
//
// Fill Validations ...
eaValidations.forceHasSwing = eaForceHasSwing;
eaValidations.forceOBBarType = eaForceOBBarType;
eaValidations.minRequiredOBBar = eaMinRequiredOBBar;
eaValidations.forceFVGBarType = eaForceFVGBarType;
eaValidations.liquidityLoopback = eaLiquidityLoopback;
eaValidations.maxAllowedRange = eaMaxAllowedRange;
eaValidations.minAllowedRange = eaMinAllowedRange;
eaValidations.forceHasFLiquidity = eaForceHasFLiquidity;
eaValidations.forceHasRLiquidity = eaForceHasRLiquidity;
eaValidations.validateGapSequence = eaValidateGapSequence;
eaValidations.minAllowedBlockLength = eaMinAllowedBlockLength;
eaValidations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout;
// Initializing Signaller(s) ...
string symbols[];
Add(
_Symbol,
symbols //
);
bool hasSymbols = HasChild(symbols);
if (hasSymbols)
{
//
// Prepare Signaller Inputs ...
XCATBEASignallerInputs iSignallerInputs;
//
// Fill Filters ...
//
// Common Configs ...
//
eaFilters.filterBasedOnPV = eaFilterBasedOnPV;
eaFilters.bosLoopback = eaBosLoopback;
//
// Provider Name ...
iSignallerInputs.period = _Period;
iSignallerInputs.provider = "XTRGB";
//
eaFilters.filterBasedOnSar = eaFilterBasedOnSar;
eaFilters.forceSarSwitched = eaForceSarSwitched;
eaFilters.forceSarOnBothSide = eaForceSarOnBothSide;
eaFilters.forceSarHasBreakout = eaForceSarHasBreakout;
eaFilters.forceSarHasReversalSide = eaForceSarHasReversalSide;
//
// CATB Indicator ...
iSignallerInputs.catbInputs.Default();
iSignallerInputs.catbInputs.Hide();
//
eaFilters.filterBasedOnRSI = eaFilterBasedOnRSI;
eaFilters.forceHasRSITrending = eaForceHasRSITrending;
eaFilters.forceHasRSIVPattern = eaForceHasRSIVPattern;
eaFilters.forceHasRSICrossing = eaForceHasRSICrossing;
//
// Trigger Block Validations ...
iSignallerInputs.validations.forceHasSwing = eaForceHasSwing;
iSignallerInputs.validations.forceOBBarType = eaForceOBBarType;
iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar;
iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType;
iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback;
iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange;
iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange;
iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity;
iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity;
iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence;
iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength;
iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout;
//
eaFilters.filterBasedOnADX = eaFilterBasedOnADX;
eaFilters.forceHasADXTrending = eaForceHasADXTrending;
eaFilters.forceHasADXCrossing = eaForceHasADXCrossing;
//
// Trigger Block Filters ...
//
eaFilters.filterBasedOnATR = eaFilterBasedOnATR;
eaFilters.forceHasATRTrending = eaForceHasATRTrending;
eaFilters.forceHasATRBreakout = eaForceHasATRBreakout;
//
iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV;
iSignallerInputs.filters.bosLoopback = eaBosLoopback;
//
eaFilters.filterBasedOnTrend = eaFilterBasedOnTrend;
eaFilters.forceHasTrendDir = eaForceHasTrendDir;
eaFilters.forceHasTrendPlace = eaForceHasTrendPlace;
eaFilters.forceHasTrendChange = eaForceHasTrendChange;
eaFilters.forceHasTrendTrending = eaForceHasTrendTrending;
eaFilters.forceHasTrendRejection = eaForceHasTrendRejection;
eaFilters.forceHasTrendLineInside = eaForceHasTrendLineInside;
eaFilters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide;
//
iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar;
iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched;
iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide;
iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout;
iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide;
//
eaFilters.filterBasedOnDelta = eaFilterBasedOnDelta;
eaFilters.filterBasedOnVolume = eaFilterBasedOnVolume;
eaFilters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar;
eaFilters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar;
//
iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI;
iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending;
iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern;
iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing;
//
iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX;
iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending;
iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing;
//
iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR;
iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending;
iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout;
//
iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend;
iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir;
iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace;
iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange;
iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending;
iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection;
iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside;
iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide;
//
iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta;
iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume;
iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar;
iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar;
//
// Loop Through Symbols for Signalling Initializing ...
int symbolsCount = ArraySize(symbols);
for (int i = 0; i < symbolsCount; i++)
{
//
string iSymbol = symbols[i];
//
iSignallerInputs.symbol = iSymbol;
if (iSignallerInputs.IsValid())
{
//
// Initialize Signaller ...
XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs);
//
// Add it to the Signallers List ...
Add(
iSignaller,
eaSignallers //
);
//
ZeroMemory(iSignaller);
}
}
//
// Cleanup Resources ...
iSignallerInputs.Clean();
}
//
}
-814
View File
@@ -141,19 +141,6 @@ enum ENUM_X_SIGNAL_EXECUTION_RESULT
X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params
};
//
// Available Guard Action ...
enum ENUM_X_GUARD_ACTIONS
{
X_GUARD_ACTION_NOTHING, // Nothing
X_GUARD_ACTION_HEDGE, // Hedge
X_GUARD_PARTIAL_CLOSE, // Partial Close
X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss
X_GUARD_ACTION_FORCE_CLOSE, // Force Close
X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal
X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders
};
//
enum ENUM_X_POSITION_TYPES
{
@@ -2585,320 +2572,6 @@ struct XOnTradeHandlerState
}
};
//
// Model Guard Info ...
struct XGuard
{
//
string symbol; // Trading Symbol ...
string provider; // Signal Provider ...
ENUM_TIMEFRAMES period; // Trading Timeframe ...
ENUM_X_POSITION_TYPES type; // Position Type ...
ENUM_X_GUARD_ACTIONS action; // Which Action to Do ...
//
double dblPayLoad;
string strPayload;
//
// Constructor ...
XGuard()
{
Clean();
}
//
// Initialize ...
//
// Global Initializer ...
bool Init(
string mSymbol, // Trading Symbol ...
ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ...
ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ...
ENUM_X_POSITION_TYPES mType = NULL, // Position Type ...
string mProvider = NULL, // Signal Provider ...
double mDblPayLoad = NULL,
string mStrPayload = NULL //
)
{
//
type = mType;
symbol = mSymbol;
period = mPeriod;
action = mAction;
provider = mProvider;
dblPayLoad = mDblPayLoad;
strPayload = mStrPayload;
//
bool result = IsValid();
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
symbol = NULL;
provider = NULL;
period = NULL;
action = X_GUARD_ACTION_NOTHING;
//
strPayload = NULL;
dblPayLoad = EMPTY_VALUE;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
action != X_GUARD_ACTION_NOTHING
//
;
//
return result;
}
};
//
// Model a Position with all of it's Supports ...
struct XPositionPack
{
//
ulong ticket; // Main Position's Ticket
//
XPosition position; // Main Position (if Exists)
//
int supportOrdersCount; // Supported Orders (Untriggered)
int supportPositionsCount; // Supported Positions
//
XOrder supportOrders[]; // Supported Orders (Untriggered)
XPosition supportPositions[]; // Supported Positions
//
// Constructor ...
XPositionPack()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
ticket = 0;
//
position.Clean();
//
supportOrdersCount = 0;
supportPositionsCount = 0;
//
Clean(supportOrders);
Clean(supportPositions);
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
NotEmpty(ticket) &&
(
//
supportOrdersCount > 0
? ArraySize(supportOrders) == supportOrdersCount
: true
//
)
//
&&
//
(
//
supportPositionsCount > 0
? ArraySize(supportPositions) == supportPositionsCount
: true
//
)
//
;
//
return result;
}
};
//
// Check Position SL Trails Structure ...
struct XTrail
{
//
ulong ticket; // Position Ticket ...
ENUM_POSITION_TYPE type; // Type ...
datetime time; // Trail Time ...
double before; // SL Value Before Trailing ...
double after; // SL Value After Trailing ...
int level; // Number of Trails SL ...
double profit; // Profit in SL Time ...
//
// Constructor ...
XTrail()
{
Clean();
}
//
// Tools ...
//
bool Init(
ulong mTicket, // Ticket
ENUM_POSITION_TYPE mType, // Type
double mProfit, // Profit
double mBefore, // Before
double mAfter // After
)
{
//
Clean();
//
type = mType;
after = mAfter;
ticket = mTicket;
before = mBefore;
profit = mProfit;
//
level++;
//
time = TimeCurrent();
//
return IsValid();
}
//
bool Update(
double mSl, // new SL ...
double mProfit // Profit
)
{
//
bool result = false;
//
time = TimeCurrent();
//
double cAfter = after;
after = mSl;
before = cAfter;
profit = mProfit;
//
level++;
//
result = IsValid();
//
return result;
}
//
string GenerateTag()
{
//
string result = NULL;
//
string ticketLevelStr = ToString(ticket) + "," + ToString(level);
//
result = Surround(
XSLTrailToken,
ticketLevelStr //
);
//
return result;
}
//
// Cleanup ...
void Clean()
{
//
ticket = 0;
time = 0;
before = 0;
after = 0;
level = 0;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
ticket > 0 &&
time > 0 &&
level > 0
//
;
//
return result;
}
};
//
struct XSymbolPositions
{
@@ -3508,493 +3181,6 @@ struct XSymbolPositions
//
};
//
struct XSymbolLastPosition
{
//
string symbol;
string provider;
datetime time;
//
XSymbolLastPosition()
{
Clean();
}
//
// Tools ...
void Clean()
{
//
time = NULL;
symbol = NULL;
provider = NULL;
//
ZeroMemory(this);
}
};
//
// 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 swap; // Swap
double profit; // Profit on Close
double commission; // Commission
double maxDrawdown; // Max Position Drawdown
string message; // Close Reason
datetime endTime; // End Time
//
XSignal signal; // Signal Object
int pushers; // Signal Pushers
string conditions; // Signal Conditions
//
// 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;
}
//
signal = _signal;
time = _signal.time;
entry = _signal.entry;
symbol = _signal.symbol;
volume = _signal.volume;
period = _signal.period;
provider = _signal.provider;
conditions = _signal.conditions;
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;
//
if (profit < 0 &&
(maxDrawdown == 0 ||
MathAbs(profit) > MathAbs(maxDrawdown)))
{
maxDrawdown = profit;
}
//
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;
maxDrawdown = 0;
//
signal.Clean();
//
ResetTrail();
ResetRecovery();
//
ZeroMemory(this);
}
//
// 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) +
//
// Attach Trade Info ...
(onlySignals
? ""
:
//
"-------------" + "\n" +
ToString("Volume", volume) +
ToString("Profit", profit) +
ToString("Commission", commission) +
ToString("Swap", swap) +
ToString("Max Drawdown", maxDrawdown) +
ToString("End Time", endTime) +
ToString("Age", age) +
ToString("Message", message) +
""
//
) +
//
// Attach Conditions to Signals ...
(!onlySignals
? ""
:
//
"-------------" + "\n" +
ToString("Pushers", pushers) +
"Conditions:" + "\n" +
"-------------" + "\n" +
conditions +
""
//
) +
//
""
//
;
//
return result;
}
//
// There are some Controlling Situations for each Trade
// which implemented here ...
//
// Trailing Stop ....
//
bool allowTrailStop; // Specified Position Can Trail Stop or not
bool ignoreTPOnTrail; // Ignore TP when SL Trailed
bool trailBasedOnProfit; // Do Trail Based on Profit Points
int trailLevel; // Last Trail Level
double trailStartInPoint; // Trail Starts When Profits Growing in Point
double trailStepInPoint; // Profit Must Grows Point to do Trailling
//
// Reset all Trailing Configurations ....
void ResetTrail()
{
//
trailLevel = 0;
trailStepInPoint = 0;
trailStartInPoint = 0;
allowTrailStop = false;
ignoreTPOnTrail = false;
trailBasedOnProfit = false;
}
//
// 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
double recoveryVolume; // Next Recovery Positioin Volume
ENUM_X_POSITION_TYPES recoveryLookingType; // Looking for Next Recovery Type
//
void ResetRecovery()
{
//
allowRecover = false;
recoveryLevel = 0;
recoveryVolume = 0;
recoveryTPPoint = 0;
recoverySLPoint = 0;
recoveryVolumeMultiplier = 0;
recoveryLookingType = X_POSITION_TYPE_NONE;
}
//
};
//
// TypeDefs ...
+523 -2
View File
@@ -22,8 +22,8 @@
//
// Imports ...
#include "../../Classes/x-saherelm.x-alert.class.mq5"
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-guard.class.mq5"
#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5";
#include "../Classes/xcatbea.x-poi.detector.class.mq5";
#include "../Classes/xcatbea.x-poi.drawer.class.mq5";
@@ -33,6 +33,527 @@
//
// Definitions ...
class XCXCATBEASignaller : XCBaseAlert
//
struct XCATBEASignallerInputs
{
//
// Pros ...
string symbol;
string provider;
ENUM_TIMEFRAMES period;
X121XCatbInputs catbInputs;
XTriggerBlockFilters filters;
XTriggerBlockValidationRules validations;
//
// Constructor(s) ...
XCATBEASignallerInputs()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
symbol = NULL;
period = NULL;
provider = NULL;
filters.Clean();
catbInputs.Clean();
validations.Clean();
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
IsValid(symbol) &&
IsValid(period) &&
IsValid(provider) &&
catbInputs.IsValid();
//
return result;
}
//
};
class XCXCATBEASignaller : XCBase
{
//
// Public ...
public:
//
// Props ...
//
bool useGuards; // Use Guards or not ...
bool allowDraws; // Allow Draws or not ...
//
XBarTracker barTraker; // Bar Tracker ...
XCX121XCatbHelper *helper; // XCATB Helper Class instance ...
XCBarAnalyser *barAnalyser; // Bar Analyser ...
XCXCATBEAPOIDrawer *drawer; // POI Drawer ...
XCXCATBEAPOIDetector *detector; // POI Detector ...
//
XCATBEAStrategyConditions mConditions;
XCATBEAStrategyConditions mConditionsCollection[];
//
// Constructor ...
XCXCATBEASignaller(XCATBEASignallerInputs &inputs)
{
Init(inputs);
}
//
// Deconstructor ...
~XCXCATBEASignaller()
{
DeInit();
}
//
// Properties ...
//
string GetSymbol()
{
return symbol;
}
//
string GetProvider()
{
return provider;
}
//
ENUM_TIMEFRAMES GetPeriod()
{
return period;
}
//
// Tick Analyser ...
/**
* Process Tick ...
*/
void ProcessTick(
XPosition &positions[],
XGuard &guards[],
XCATBEAStrategyConditions &conditions //
)
{
//
Clean(guards);
conditions.Clean();
//
int count = 0;
bool has = false;
int barIndex = 0;
//
// Check Guards ...
has = DetectGuards(
guards,
positions,
barIndex //
);
//
// Check Triggered Conditions ...
has = HasChild(mConditionsCollection);
if (has)
{
//
int selectedIDX = -1;
count = ArraySize(mConditionsCollection);
for (int i = 0; i < count; i++)
{
//
// Select indexed Conditions ...
XCATBEAStrategyConditions iConditions = mConditionsCollection[i];
//
// Check Conditions Triggered ...
has = DetectSignalTrigger(
iConditions,
barIndex //
);
if (has)
{
//
selectedIDX = i;
conditions = iConditions;
iConditions.Clean();
//
break;
}
//
iConditions.Clean();
}
//
// Check Can Trigger ...
has = IsValidIndex(selectedIDX) &&
conditions.IsValid() &&
conditions.IsSetuped() &&
conditions.CanTrigger();
if (has)
{
//
ArrayRemove(
mConditionsCollection,
selectedIDX,
1 //
);
}
else
{
conditions.Clean();
}
}
//
// Check Bar Processing ...
if (!barTraker.CanProcessBar())
{
return;
}
//
// Check Signal Setups ...
has = DetectSignalSetup(barIndex);
if (has) {
//
barTraker.Waits();
//
AddConditionsIfNotExists();
//
mConditions.Clean();
}
}
//
// Signalling Tools ...
/**
* Detect Setup Conditions based on Signalling ...
*
* @param maxAllowedSLDistanceInPoint: int, Max Allowed SL Distance in Points (if Bigger thn Zero Provided) ...
*
* @return ( bool )
*/
bool DetectSignalSetup(int barIndex = 0)
{
//
bool result = false;
//
// Normalize Args ...
barIndex = NormalizeInt(barIndex, 0);
//
// Cleanup Resource ...
//
return result;
}
/**
* Detect Trigger Conditions for Specified Signal ...
*
* @param conditions: XCATBEAStrategyConditions instance Reference, Specified Signal Conditions ...
* @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ...
*
* @return ( bool )
*/
bool DetectSignalTrigger(
XCATBEAStrategyConditions &conditions,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize Args ...
barIndex = NormalizeInt(barIndex, 0);
//
// Validate Setup ...
result = conditions.IsSetuped();
if (!result)
{
return result;
}
//
// Cleanup Resources ...
//
return result;
}
/**
* Detect Guards bsed on Signalling Class ...
*
* @param guards: XCAEAGuard instance Collection, Holds Provided Guards ...
* @param positions: XPosition instance Collection, Provides Signalling Based Positions for Apply Guards on them ...
* @param provider: X121SMCStrategySignalProviderData instance Reference, Specified Data for Cycles ...
*
* @return ( bool )
*/
bool DetectGuards(
XGuard &guards[],
const XPosition &positions[],
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize Args ...
barIndex = NormalizeInt(barIndex, 0);
//
// TODO: Implement this ...
//
// Cleanup Resources ...
//
return result;
}
//
// Protected ...
protected:
//
/**
* Initialize ...
*/
void Init(XCATBEASignallerInputs &inputs)
{
//
bool has = inputs.IsValid();
if (!has)
{
return;
}
//
symbol = inputs.symbol;
period = inputs.period;
provider = inputs.provider;
//
// Initialize Bar Tracker ...
has = barTraker.Init(
symbol,
period //
);
if (!has)
{
return;
}
//
// Initialize Bar Analyser ...
barAnalyser = new XCBarAnalyser();
//
// initialize Helper ...
has = helper.Init(
symbol,
period,
inputs.catbInputs //
);
if (!has)
{
return;
}
//
mConditions.Clean();
Clean(mConditionsCollection);
//
InitPOI();
}
/**
* DeInitialize ...
*/
void DeInit()
{
//
drawer.Clear();
delete drawer;
ZeroMemory(drawer);
//
detector.CleanPivots();
delete detector;
ZeroMemory(detector);
//
delete helper;
ZeroMemory(helper);
//
delete barAnalyser;
ZeroMemory(barAnalyser);
//
barTraker.Clean();
}
/**
* Add Conditions to Conditions Collection if not Exists ...
*
* @param maxAllowed: int, Specified Max Allowed Holding Conditions ...
*
* @return ( int )
*/
int AddConditionsIfNotExists(
int maxAllowed = 10 //
)
{
//
int result = 0;
//
bool isSetuped = IsValid(mConditions.setupTime) &&
HasDirection(mConditions.dir);
if (!isSetuped)
{
return result;
}
//
int count = ArraySize(mConditionsCollection);
if (IsValidSize(count))
{
//
// Copy Original Items ...
XCATBEAStrategyConditions tmpItems[];
Copy(
mConditionsCollection,
tmpItems //
);
//
// Prese Item Data ...
bool isBullish = IsBullish(mConditions.dir);
//
for (int i = 0; i < count; i++)
{
//
XCATBEAStrategyConditions iItem = tmpItems[i];
//
bool canRemove = mConditions.dir == iItem.dir &&
mConditions.pivot == iItem.pivot;
if (canRemove)
{
//
ArrayRemove(
mConditionsCollection,
i,
1 //
);
}
}
//
Clean(tmpItems);
}
//
AddRef(
mConditions,
mConditionsCollection //
);
//
// Remove Olds ...
CleanupArray(
mConditionsCollection,
maxAllowed //
);
//
result = ArraySize(mConditionsCollection);
//
return result;
}
//
// Private ...
private:
//
// Props ...
string symbol;
string provider;
ENUM_TIMEFRAMES period;
//
// Initialize and Configure POI Detector and Drawer ...
void InitPOI()
{
//
// Initialize POI Detector ...
bool has = helper != NULL;
if (has)
{
//
detector = new XCXCATBEAPOIDetector(helper);
//
// Configure ...
}
//
// Initialize POI Drawer ...
has = detector != NULL;
if (has)
{
//
drawer = new XCXCATBEAPOIDrawer(detector);
//
// Configure ...
}
}
//
};
@@ -533,6 +533,21 @@ class XCXCATBEAPOIDetector : public XCBase
{
}
//
void CleanPivots()
{
//
Clean(invalidPivots);
//
peakPivot.Clean();
valePivot.Clean();
//
Clean(peakPivots);
Clean(valePivots);
}
//
// Pivots ...
@@ -1372,21 +1387,6 @@ class XCXCATBEAPOIDetector : public XCBase
return result;
}
//
void CleanPivots()
{
//
Clean(invalidPivots);
//
peakPivot.Clean();
valePivot.Clean();
//
Clean(peakPivots);
Clean(valePivots);
}
//
void SortPivots()
{
@@ -1596,6 +1596,57 @@ class XCXCATBEATradeManager : public XCBaseAlert
return result;
}
/**
* Retrieve Specified Positions ...
*
* @param positions: XPosition instance Reference Array, which holds Founded Positions ...
* @param symbol: string, Specified Symbol Name ...
* @param provider: string, Specified Provider Name ...
* @param period: ENUM_TIMEFRAMES, Specified Period ...
*
* @return ( int )
*/
int GetPositions(
XPosition &positions[],
string symbol,
string provider,
ENUM_TIMEFRAMES period //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has =
IsValid(symbol) &&
IsValid(period) &&
IsValid(provider);
if (!has)
{
return result;
}
//
result = trader.GetPositions(
positions,
symbol,
provider,
period,
NULL, // All Types ...
true, // Filter By Magic ...
true // Force Clean ...
);
//
result = ArraySize(positions);
//
return result;
}
/**
* Handle Position Take Profit ...
*
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff