Files
xMQL5/MQLTestWorkspace/BKPS/14030222/Classes/x-saherelm.x121.xea.class.mq5
T
2024-05-11 05:36:03 +03:30

1865 lines
50 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XSCX121EA
// Description: an Expert Class which
// used X121 Setup ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// START Import and Inclused requirements ...
//
//
// Includes ...
#include "../Classes/x-saherelm.xea.class.mq5"
#include "../Libraries/x-saherelm.x121.draw.lib.mq5"
#include "../Classes/x-saherelm.x121.provider.class.mq5"
//
// END Import and Inclused requirements ...
//
//
// START Definitions ...
//
//
// END Definitions ...
//
//
// START Overrides ...
//
//
// END Overrides ...
//
//
// an Expert Advisor Class by X121Provider ...
class XSCX121EA : public XSCBaseEA
{
//
// Public ...
public:
//
// Props ...
//
// Constructor ...
void XSCX121EA(
string symbol, // Trading Symbol
ENUM_TIMEFRAMES period, // Trading Time Frame
ulong magic, // Magic Number
int slippage, // Slippgae
double maxAllowedSpread = 0, // Max Allowed Spread to Execute Signal
int maxAllowedPositions = 0, // Maximum Allowed Same Time Position
double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge)
double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge)
double maxAllowedDrawDownFactor = 0, // Max Allowed Drawdown factor for Open New Positions
TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler
TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler
TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler
TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler
TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler
TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler
//
int minAgeForDoSupport = 0, // Minimum Position Age for Do Supporting
int minAgeForUpdateSupports = 0, // Minimum Age for Update Untriggered Support Orders
TOnSignalConditions onSignalConditions = NULL // On SignalConditions Event Handler
) : XSCBaseEA(symbol,
period,
magic,
slippage,
maxAllowedSpread,
maxAllowedPositions,
minProfitPerTrade,
minProfitPerVolumeFactor,
maxAllowedDrawDownFactor,
onStopLossTriggered,
onTakeProfitTriggered,
onDealsChangedHandler,
onOrdersChangedHandler,
onPositionsChangedHandler,
onTradeStateChangedHandler)
{
//
mOnSignalConditions = onSignalConditions;
mMinAgeForDoSupport = minAgeForDoSupport;
mMinAgeForUpdateSupports = minAgeForUpdateSupports;
}
//
// DeConstructor ...
void ~XSCX121EA()
{
//
// Delete All Registered Providers ...
int providersCount = ArraySize(mProviders);
if (providersCount > 0)
{
//
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iProvider = mProviders[i];
//
delete iProvider.provider;
}
}
}
//
// START Properties ...
//
//
// Min Profit Per Trade ...
//
bool MinProfitPerTrade(double value)
{
//
bool result = false;
//
if (value <= 0)
{
return result;
}
//
result = value > 0;
if (value == mMinProfitPerTrade)
{
return result;
}
//
mMinProfitPerTrade = value;
//
return result;
}
//
double MinProfitPerTrade()
{
return mMinProfitPerTrade;
}
//
// Min Profit Per Volume Factor ...
//
bool MinProfitPerVolumeFactor(double value)
{
//
bool result = false;
//
if (value <= 0)
{
return result;
}
//
result = value > 0;
if (value == mMinProfitPerVolumeFactor)
{
return result;
}
//
mMinProfitPerVolumeFactor = value;
//
return result;
}
//
double MinProfitPerVolumeFactor()
{
return mMinProfitPerVolumeFactor;
}
//
// Add Provider ...
bool AddProvider(
X121SignalProvider &provider // Specific Provider ...
)
{
//
bool result = false;
//
// Validate Provider ...
if (provider.symbol == NULL ||
provider.period == NULL ||
provider.riskAmount <= 0 ||
StringLen(provider.symbol) == 0 ||
ArraySize(provider.providers) == 0)
{
return result;
}
//
// Check Exists or not ...
int idx = GetProviderIndex(
provider.symbol,
provider.period);
if (idx >= 0)
{
return result;
}
//
PrepareProviderConfig();
//
// Make Instance of X121Provider Class ...
provider.provider = new XSCX121Provider(
provider.symbol,
provider.period,
true // Ignore Ticks after Recieved a Signal Till new Candle ...
);
//
// Attach Event Listener ...
if (mOnSignalConditions != NULL)
{
//
// Attach Event Handlers ...
provider.provider.AddOnSignalConditionEventHandler(mOnSignalConditions);
}
//
// Set Signallers to Provider Class ...
result = provider.provider.SetSignallers(provider.providers);
if (!result)
{
return result;
}
//
// Initialize Provider ...
result = provider.provider.SetConfig(mProviderConfig);
//
// Add Prepared Provider to Providers ...
Add(
provider,
mProviders);
//
return result;
}
//
// Add Providers ...
int AddProviders(
X121SignalProvider &providers[] // Specific Providers ...
)
{
//
int result = 0;
//
int providersCount = ArraySize(providers);
if (providersCount <= 0)
{
return result;
}
//
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iProvider = providers[i];
//
bool isAdded = AddProvider(iProvider);
if (isAdded)
{
result++;
}
}
//
return result;
}
//
// END Properties ...
//
//
// START Overrides ...
//
//
void OnPositionsChangedHandler(int count)
{
}
//
// Handle TakeProfit Event ...
void OnTakeProfitTriggered(const XDeal &deal)
{
//
// Since we Use Hedge in Min Profit ...
// Some times a Position Modified and SL Trails ...
// this Position closed through sl Event ...
// here we Must Close positions's Pack Orders ...
//
// So We Have to Get Positions Pack ...
XPositionPack dealPack;
bool hasPack = mTrader.GetDealPack(
deal,
dealPack);
if (hasPack)
{
HandleClosePack(dealPack);
}
//
CancelAllEQMOrders();
}
//
// Handle StopLoss Event ...
void OnStopLossTriggered(const XDeal &deal)
{
//
// Since we Use Hedge in Min Profit ...
// Some times a Position Modified and SL Trails ...
// this Position closed through sl Event ...
// here we Must Close positions's Pack Orders ...
//
// So We Have to Get Positions Pack ...
XPositionPack dealPack;
bool hasPack = mTrader.GetDealPack(
deal,
dealPack);
if (hasPack)
{
HandleClosePack(dealPack);
}
//
CancelAllEQMOrders();
}
//
// END Overrides ...
//
//
// START Inheritance Functions ...
//
//
void PrepareTag()
{
mTag = "X121EA:" + mSymbol + "," + ToString(mPeriod) + (string)mMagic;
}
//
// Check Providers Guard States ...
bool CheckGuard(XGuard &guards[])
{
//
bool result = false;
//
Clean(guards);
//
// Positions Management ...
// HandlePositionManagement();
//
int providersCount = ArraySize(mProviders);
if (providersCount <= 0)
{
return result;
}
//
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iProvider = mProviders[i];
//
XGuard iGuards[];
bool iHasGuard = iProvider.provider.GuardCheck(iGuards);
if (iHasGuard)
{
//
Copy(
iGuards,
guards,
false);
}
}
//
// Here we Can Implement Custom Guards Senario ...
//
// Do Management Equity ...
XSignal signals[];
HandleEQM(signals);
//
result = ArraySize(guards) > 0;
//
return result;
}
//
// Check Providers for Signals ...
bool SignalCheck(XSignal &signals[])
{
//
bool result = false;
//
Clean(signals);
//
// Since We may have Custom Supporting Senarios for Positions
// if there is no Equity or Positions Count Passed ...
// we Clear Account Policies Check here and do it after
// recieveing Signals ...
//
// Check Providers Count ...
int providersCount = ArraySize(mProviders);
if (providersCount <= 0)
{
return result;
}
//
// Here we proccess all Exists Registered Providers and get
// probably signals and add them signals Array ...
//
// Loop through Providers to Recieve Market Sence based on each them ...
for (int i = 0; i < providersCount; i++)
{
//
// Get provider Descriptor Struct ...
X121SignalProvider iProvider = mProviders[i];
//
// Check Provider Pivot Point Ready ...
int iFoundedPivots = iProvider.provider.CountPivots();
int iReuiredPivots = iProvider.provider.GetMinPivots();
if (iFoundedPivots < iReuiredPivots)
{
//
// Start Retrieveing Pivot Points ...
iProvider.provider.ProccessPivotPoints();
//
// ignore Calculating Signals since Pivot Points recieved ...
continue;
}
//
// Retrieve Market Consitions from Specified Provider ...
X121MarketConditions iConditions;
bool iHasSignal = iProvider.provider.ProcessTick(iConditions);
//
// Check there is Signal or not ...
if (iHasSignal && iConditions.hasSignal)
{
//
// Check Signalling is Enabled by Signal type ...
bool isiSignalLong = IsLong(iConditions.signal.type);
if ((isiSignalLong && !mEnableLongs) ||
(!isiSignalLong && !mEnableShorts))
{
continue;
}
//
// Add Signal to Retrieved Signals Collection ...
Add(
iConditions.signal,
signals);
}
}
//
// Check Signals Exists for Processing ...
result = ArraySize(signals) > 0;
//
return result;
}
//
// Before Base EA Class Execute Signals ...
// this Action Run to Implement Custom Management ...
void BeforeSignalExecution(
XSignal &signals[] // Base EA Checked Signals ...
)
{
//
// Implement Custom Signal Executing Senario Here ...
HandleEQM(signals);
//
// Here we force Signaller Signals must be in Profit ...
CheckSignalsProviderState(signals);
}
//
// END Inheritance Functions ...
//
//
// START Provided Actions ...
//
//
// END Provided Actions ...
//
//
// EQM Props ...
//
//
int MinAgeForDoSupport()
{
return mMinAgeForDoSupport;
}
//
void MinAgeForDoSupport(int value)
{
//
if (value <= 0)
{
value = 0;
}
//
if (value == mMinAgeForDoSupport)
{
return;
}
//
mMinAgeForDoSupport = value;
}
//
int MinAgeForUpdateSupports()
{
return mMinAgeForUpdateSupports;
}
//
void MinAgeForUpdateSupports(int value)
{
//
if (value <= 0)
{
value = 0;
}
//
if (value == mMinAgeForUpdateSupports)
{
return;
}
//
mMinAgeForUpdateSupports = value;
}
//
// Protected ...
protected:
//
// Private ...
private:
//
// Props ...
X121SignalProvider mProviders[];
X121ProviderInputs mProviderConfig;
TOnSignalConditions mOnSignalConditions;
//
// Actions ...
//
// EQM ...
//
//
int mMinAgeForDoSupport;
int mMinAgeForUpdateSupports;
//
bool ExecuteEQMSignal(
const XSignal &signal, // Source Signal ...
ENUM_X_SIGNAL_EXECUTION_FAILED &reason, // Provides Error Reason ...
bool checkPoliciese = true // Check Account Policies Before Execute Signal ...
)
{
//
bool result = false;
reason = X_NOTHING;
//
// Check Account Policies ...
if (checkPoliciese)
{
//
// First Check Equity ...
result = CheckEquityForTrade();
if (!result)
{
//
reason = X_FAILED_REASON_EQUITY;
return result;
}
//
// Check Positions Count ...
result = ChecPositionsForTrade();
if (!result)
{
//
reason = X_FAILED_REASON_MAX_REACHED;
return result;
}
//
// Check Spread ...
result = IsSpreadOkForSignalExecution(signal);
if (!result)
{
//
reason = X_FAILED_REASON_SPREAD;
return result;
}
}
//
XSignal tmpSignal = signal;
PrepareSignal(tmpSignal);
//
// Generate Provider Comment ...
string comment = GenerateXEQMSupportComment();
//
result = mTrader
.ExecuteSignal(
tmpSignal,
comment //
);
if (!result)
{
reason = X_UNKNOWN;
}
//
return result;
}
//
// Execute Specific Signals by Checking Spreads ...
// if provided ...
int ExecuteEQMSignals(
const XSignal &signals[], // Signals Collection ...
ENUM_X_SIGNAL_EXECUTION_FAILED &reasons[], // Provides Error Reason ...
bool checkPoliciese = true // Check Account Policies Before Execute Signal ...
)
{
//
int result = 0;
//
Clean(reasons);
//
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
// Here we Have to Check Account Policies
// and Execute Signals base on them ...
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
ENUM_X_SIGNAL_EXECUTION_FAILED iReason = X_NOTHING;
//
bool isExecuted = ExecuteEQMSignal(
iSignal,
iReason,
checkPoliciese //
);
if (isExecuted)
{
result++;
}
//
Add(
iReason,
reasons);
}
//
return result;
}
//
// Retrieve All EQM Placed Support Orders ...
int GetEQMOrders(
XOrder &orders[] // Hold Result
)
{
//
int result = 0;
//
XOrder allOrders[];
int allOrdersCount = GetOrders(allOrders);
if (allOrdersCount <= 0)
{
return result;
}
//
// Extract EQM Orders ...
result = GetEQMSupportOrders(
orders,
allOrders);
//
return result;
}
//
// Retrieve All EQM Support Positions ...
int GetEQMPositions(
XPosition &positions[] // Hold Result
)
{
//
int result = 0;
//
XPosition allPositions[];
int allPositionsCount = GetPositions(allPositions);
if (allPositionsCount <= 0)
{
return result;
}
//
// Extract EQM Positions ...
result = GetEQMSupportPositions(
positions,
allPositions);
//
return result;
}
//
// Count all open Positions Volume for supports ...
double GetEQMSupportVolume(
bool ignoreEQM = true // Ignore EQM Positions
)
{
//
double result = 0;
//
// TODO:
// add to Props ...
double maxEQMSupportVolume = 0.3;
//
// Retrieve Positions ...
XPosition positions[];
int positionsCount = GetPositions(positions);
if (positionsCount <= 0)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
// Check Current Position is EQM Position Or Not ...
bool isEQM = IsEQMSupport(iPosition.comment);
if (isEQM && ignoreEQM)
{
continue;
}
//
result += iPosition.volume;
}
//
// Multiply Volume Summary ...
// TODO: Make it Configurable ...
result *= 1;
if (result > maxEQMSupportVolume)
{
result = maxEQMSupportVolume;
}
//
return result;
}
//
// Cancel all EQM Placed Support Orders ...
bool CancelAllEQMOrders()
{
//
bool result = false;
//
XOrder eqmOrders[];
int eqmOrdersCount = GetEQMOrders(eqmOrders);
if (eqmOrdersCount <= 0)
{
return result;
}
//
result = mTrader.CancelOrders(eqmOrders);
//
return result;
}
//
// Add Support Signals based on EQM Algo ...
void DoEQMSupport(
const XSignal &signals[], // this used when signallers call EQM ...
const XPosition &positions[] // positions for supporting using EQM ...
)
{
//
// Check EQM is Enabled Or Not ...
bool isEQMEnable = mMinAgeForDoSupport > 0 &&
mMinAgeForUpdateSupports > 0;
if (!isEQMEnable)
{
return;
}
//
bool doSupportPivots = false;
bool doSupportByFibos = true;
bool doSupportBySignals = true;
//
int signalsCount = ArraySize(signals);
int positionsCount = ArraySize(positions);
//
if (positionsCount <= 0)
{
//
// We can Ignore this when
// we need to Support Positions Only ...
// for Other Reasons ...
return;
}
//
// NOTE:
// we Have to Check Previously Supported Signals ...
// and Extract Longest Age ...
// then if the Age is Long enough for Updating, Cncell All EQM Orders ...
// other wise we have to waits untill Market Decide what to do ...
XOrder orders[];
int ordersCount = GetEQMOrders(orders);
if (ordersCount > 0)
{
//
XOrder oldestOrder;
int oldestOrderAge = GetOldest(
oldestOrder,
orders);
//
if (oldestOrderAge <= 0)
{
return;
}
//
bool isOldEnoughForCancel =
oldestOrderAge >= mMinAgeForUpdateSupports;
if (!isOldEnoughForCancel)
{
//
// There are Enabled EQM Orders ...
// so we have to wait for them ...
return;
}
else
{
//
// Here we Cancel Pending Orders ...
CancelAllEQMOrders();
}
}
//
// All Support Signals from
// each Senario collect into this
// and then Executed Once ...
XSignal supports[];
//
double volume = GetEQMSupportVolume(
false // doesnt ignore eqm position volumes for supporting
);
//
// SENARIO:
//
// IND: (in drawdown)
// - Find Min Profit of InD Positions ...
// - Find Max Profit of InD Positions ...
//
// INP: (in profit)
// - Find Min Profit of InD Positions ...
// - Find Max Profit of InD Positions ...
//
XPosition inDPositions[];
XPosition inPPositions[];
ExtractPositionsBasedOnProfits(
positions,
inDPositions,
inPPositions //
);
//
double maxP = 0;
double minP = 0;
int maxInPPositionIDX = -1;
int minInPPositionIDX = -1;
int inPPositionsCount = ArraySize(inPPositions);
if (inPPositionsCount > 0)
{
//
// Find Min and Max ...
for (int i = 0; i < inPPositionsCount; i++)
{
//
XPosition iPosition = inPPositions[i];
//
maxP =
maxP == 0 || maxP < iPosition.profit
? iPosition.profit
: maxP;
if (maxP == iPosition.profit)
{
maxInPPositionIDX = i;
}
//
minP =
minP == 0 || minP > iPosition.profit
? iPosition.profit
: minP;
if (minP == iPosition.profit)
{
minInPPositionIDX = i;
}
}
}
//
double maxD = 0;
double minD = 0;
int maxInDPositionIDX = -1;
int minInDPositionIDX = -1;
int inDPositionsCount = ArraySize(inDPositions);
if (inDPositionsCount > 0)
{
//
// Find Min and Max ...
for (int i = 0; i < inDPositionsCount; i++)
{
//
XPosition iPosition = inDPositions[i];
//
maxD =
maxD == 0 || maxD < iPosition.profit
? iPosition.profit
: maxD;
if (maxD == iPosition.profit)
{
maxInDPositionIDX = i;
}
//
minD =
minD == 0 || minD > iPosition.profit
? iPosition.profit
: minD;
if (minD == iPosition.profit)
{
minInDPositionIDX = i;
}
}
}
//
// For InDPositions:
// it is so Better for US to Follow In Profit Positions for Supporting ...
// if they aren't any in profit Position then start Supporting In DrawDown Positions ...
bool canSupportInDPositions = maxInPPositionIDX == -1 &&
minInPPositionIDX == -1;
//
// Here we have all we want ...
// Next step is to Implement EQM Supporting Senarios ...
//
// SENARIO:
// - Using Pivots (Support and Resistances);
// ---> find pivots on it's side and place support:
// - Using Fibonacci;
// - Using Provided Signals;
//
// Using Pivots For Supporting ...
if (doSupportPivots)
{
//
// this must be contains all available pivots ...
double price;
string symbol;
double pivots[];
XOHCLSupRes supRes;
double rateStep = 15;
ENUM_TIMEFRAMES period;
//
// here we have to loop through all available providers and retrieve pivots
// then add them to our pivots if their not Exists ...
int providersCount = CountProviders();
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iSignalProvider = mProviders[i];
//
// Extract iSignalProvider's Pivots ...
double iPivots[];
int iPivotsCount = iSignalProvider
.provider
.FillPivotPoints(iPivots);
if (iPivotsCount <= 0)
{
continue;
}
//
// Fill their Values to Main Array ...
// if they are not exists ...
AddsIfNotExists(
iPivots,
pivots);
}
//
int pivotsCount = ArraySize(pivots);
if (pivotsCount > 0)
{
//
// Here we Can Do EQM Support based on Pivots ...
//
// TODO: Make these Configurable ...
bool placeTP = false;
bool placeSL = false;
bool useBoundaryForTPSL = true;
int numberOfPivotsAroundPrice = 5;
//
if (maxInPPositionIDX >= 0 && false)
{
//
// this means we have max in profit Position ...
// and this is much better to guard it ...
//
symbol = inPPositions[maxInPPositionIDX].symbol;
price = GetEntry(
symbol,
inPPositions[maxInPPositionIDX].type //
);
period = inPPositions[maxInPPositionIDX].period;
rateStep = PointToPrice(
symbol,
rateStep //
);
//
// Extract Required Number of Pivots ...
supRes = ExtractSupportAndResistance(
price,
pivots,
numberOfPivotsAroundPrice,
rateStep //
);
//
// now we have to Generate Support Signals based on
// retrieve XOHCLSupRes ...
GenerateSupportAndResistanceSignals(
supports, // Result ...
supRes, // Support and Resistance Model ...
symbol,
period,
price,
volume,
placeSL,
placeTP,
useBoundaryForTPSL //
);
}
//
if (minInPPositionIDX >= 0 && false)
{
//
// this means we have max in profit Position ...
// and this is much better to guard it ...
//
symbol = inPPositions[minInPPositionIDX].symbol;
price = GetEntry(
symbol,
inPPositions[minInPPositionIDX].type //
);
period = inPPositions[minInPPositionIDX].period;
rateStep = PointToPrice(
symbol,
rateStep //
);
//
// Extract Required Number of Pivots ...
supRes = ExtractSupportAndResistance(
price,
pivots,
numberOfPivotsAroundPrice,
rateStep //
);
//
// now we have to Generate Support Signals based on
// retrieve XOHCLSupRes ...
GenerateSupportAndResistanceSignals(
supports, // Result ...
supRes, // Support and Resistance Model ...
symbol,
period,
price,
volume,
placeSL,
placeTP,
useBoundaryForTPSL //
);
}
//
// For InDPositions:
if (canSupportInDPositions)
{
//
if (maxInDPositionIDX >= 0 && false)
{
//
// Extract Required Number of Pivots ...
//
symbol = inDPositions[maxInDPositionIDX].symbol;
price = GetEntry(
symbol,
inDPositions[maxInDPositionIDX].type //
);
period = inDPositions[maxInDPositionIDX].period;
rateStep = PointToPrice(
symbol,
rateStep //
);
//
// Extract Required Number of Pivots ...
supRes = ExtractSupportAndResistance(
price,
pivots,
numberOfPivotsAroundPrice,
rateStep //
);
//
// now we have to Generate Support Signals based on
// retrieve XOHCLSupRes ...
GenerateSupportAndResistanceSignals(
supports, // Result ...
supRes, // Support and Resistance Model ...
symbol,
period,
price,
volume,
placeSL,
placeTP,
useBoundaryForTPSL //
);
}
//
if (minInDPositionIDX >= 0 && false)
{
//
// Extract Required Number of Pivots ...
//
symbol = inDPositions[minInDPositionIDX].symbol;
price = GetEntry(
symbol,
inDPositions[minInDPositionIDX].type //
);
period = inDPositions[minInDPositionIDX].period;
rateStep = PointToPrice(
symbol,
rateStep //
);
//
// Extract Required Number of Pivots ...
supRes = ExtractSupportAndResistance(
price,
pivots,
numberOfPivotsAroundPrice,
rateStep //
);
//
// now we have to Generate Support Signals based on
// retrieve XOHCLSupRes ...
GenerateSupportAndResistanceSignals(
supports, // Result ...
supRes, // Support and Resistance Model ...
symbol,
period,
price,
volume,
placeSL,
placeTP,
useBoundaryForTPSL //
);
}
}
}
}
//
// Support using Provided Signals ...
if (doSupportBySignals && signalsCount > 0)
{
//
// Change Signals Volume to Support Volume ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
iSignal.sl = 0;
// iSignal.volume = volume;
//
Add(
iSignal,
supports);
}
}
//
// Support Using Fibos ...
if (doSupportByFibos)
{
//
int providersCount = CountProviders();
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iSignalProvider = mProviders[i];
//
// Extract iSignalProvider's Pivots ...
X121MarketConditions iConditions = iSignalProvider
.provider
.GetMarketConditions(0);
//
double pivots[] = {
//
iConditions.xmanInfo.peaks[0],
//
iConditions.xmanInfo.fibLevel1s[0],
iConditions.xmanInfo.fibLevel2s[0],
iConditions.xmanInfo.fibLevel3s[0],
iConditions.xmanInfo.fibLevel4s[0],
iConditions.xmanInfo.fibLevel5s[0],
//
iConditions.xmanInfo.vales[0]};
//
bool placeTP = false;
bool placeSL = false;
bool useBoundaryForTPSL = false;
double price = GetEntry(
iConditions.symbol,
POSITION_TYPE_BUY);
//
XSignal fibSignals[];
int fibSignalsCount = GenerateSequentialSignals(
fibSignals,
pivots,
iConditions.symbol,
iConditions.period,
price,
volume,
placeSL,
placeTP,
useBoundaryForTPSL //
);
if (fibSignalsCount > 0)
{
//
Copy(
fibSignals,
supports,
false);
}
}
}
//
// Here we Must Execute Support Signals ...
int supportsCount = ArraySize(supports);
if (supportsCount <= 0)
{
return;
}
//
ENUM_X_SIGNAL_EXECUTION_FAILED reasons[];
int supported = ExecuteEQMSignals(
supports,
reasons,
false // Since these are Support Signals, we Ignore Accont Policies Check ...
);
}
//
// All available Equity Actions Implemented here ...
void HandleEQM(
const XSignal &signals[] // this used when signallers call EQM ...
)
{
//
XPosition positions[];
int positionsCount = GetPositions(positions);
if (positionsCount <= 1)
{
return;
}
//
// Used Signals when EQM required ...
int signalsCount = ArraySize(signals);
//
double profit = CalculatePositionsProfit(positions);
if (profit > 0)
{
//
double requiredProfit = CalculateRequiredProfitForHedge(positions);
bool canHedge = profit > requiredProfit;
if (canHedge)
{
//
string comment = "EQM Hedge ...";
bool isHedged = mTrader.ClosePositions(
positions,
comment);
if (isHedged)
{
//
string message = "EQM Hedged (" + ToString(positionsCount) + ") in Profit: " + ToString(profit);
//
LogMessage(message);
}
}
//
return;
}
//
// Check Positions Count ...
bool isPositionsReady = ChecPositionsForTrade();
if (!isPositionsReady)
{
//
// TODO:
// Implement what is must to do when Max Positions Reached ...
// signals can Used ...
return;
}
//
// Check Equity For Trade ...
bool isEquityReady = CheckEquityForTrade();
if (!isEquityReady)
{
//
// Implement EQM Support Of Account here ...
// signals can Used ...
DoEQMSupport(
signals,
positions);
return;
}
//
// TODO: Implement other Management Senarios if required here ...
}
//
// PROVIDERS ...
//
//
// Count Attached Providers ...
int CountProviders()
{
return ArraySize(mProviders);
}
//
// Find Specific Provider Index by using give symbol and period ...
int GetProviderIndex(
string symbol, // Trading Symbol ...
ENUM_TIMEFRAMES period // Trading Time frame ...
)
{
//
int result = -1;
//
// Validate Args ...
if (period == NULL ||
symbol == NULL ||
StringLen(symbol) == 0)
{
return result;
}
//
int providersCount = ArraySize(mProviders);
if (providersCount <= 0)
{
return result;
}
//
for (int i = 0; i < providersCount; i++)
{
//
X121SignalProvider iProvider = mProviders[i];
//
if (iProvider.symbol == symbol && iProvider.period == period)
{
//
result = i;
break;
}
}
//
return result;
}
//
// Prepare Default Configurations for X121Provider Setup ...
void PrepareProviderConfig()
{
//
// Set Default X121 Provider Configurations ...
//
// XMAN ...
//
// Candle Timer ...
mProviderConfig.xmanConfig.candleTimerColor = clrGold;
mProviderConfig.xmanConfig.candleTimerCorner = CORNER_RIGHT_UPPER;
//
// Chart Style ...
mProviderConfig.xmanConfig.upColor = clrLime;
mProviderConfig.xmanConfig.downColor = clrRed;
mProviderConfig.xmanConfig.lineColor = clrLime;
mProviderConfig.xmanConfig.bearishColor = clrRed;
mProviderConfig.xmanConfig.bullishColor = clrLime;
mProviderConfig.xmanConfig.volumesColor = clrGreen;
mProviderConfig.xmanConfig.chartMode = CHART_CANDLES;
//
// Market Cycles ...
//
// Level 1 ...
mProviderConfig.xmanConfig.l1Method = X_PERIOD_AUTO;
mProviderConfig.xmanConfig.l1Period = NULL;
//
// Level 1 ...
mProviderConfig.xmanConfig.l2Method = X_PERIOD_AUTO;
mProviderConfig.xmanConfig.l2Period = NULL;
//
// Level 1 ...
mProviderConfig.xmanConfig.l3Method = X_PERIOD_AUTO;
mProviderConfig.xmanConfig.l3Period = NULL;
//
// Level 1 ...
mProviderConfig.xmanConfig.l4Method = X_PERIOD_AUTO;
mProviderConfig.xmanConfig.l4Period = NULL;
//
// Fibonacci ...
mProviderConfig.xmanConfig.fiboLevel1 = 0.236;
mProviderConfig.xmanConfig.fiboLevel2 = 0.382;
mProviderConfig.xmanConfig.fiboLevel3 = 0.5;
mProviderConfig.xmanConfig.fiboLevel4 = 0.618;
mProviderConfig.xmanConfig.fiboLevel5 = 0.764;
//
// Boundary Detection Modes ...
mProviderConfig.xmanConfig.hhMode = MODE_HIGH;
mProviderConfig.xmanConfig.llMode = MODE_LOW;
//
// Trend Detection ...
mProviderConfig.xmanConfig.trendMultiplier = 3.5;
mProviderConfig.xmanConfig.trendPriceAppliedTo = PRICE_MEDIAN;
//
// Ribbon Detection ...
mProviderConfig.xmanConfig.ribbonMode = X_MA_SMMA;
//
// Hull Trend Detection ...
mProviderConfig.xmanConfig.hullDivisor = 2.0;
mProviderConfig.xmanConfig.hullUpAppliedTo = PRICE_HIGH;
mProviderConfig.xmanConfig.hullDownAppliedTo = PRICE_LOW;
//
// SSL Channel ...
mProviderConfig.xmanConfig.sslcMode = X_MA_SMA;
mProviderConfig.xmanConfig.sslcUpAppliedTo = PRICE_HIGH;
mProviderConfig.xmanConfig.sslcDownAppliedTo = PRICE_LOW;
//
// Presentation ...
// NOTE: Since we Configure Presentation on PreDefine Section ...
// here we turn of all Presentations as Default ...
mProviderConfig.xmanConfig.showCandleTimer = false;
mProviderConfig.xmanConfig.showCandles = false;
mProviderConfig.xmanConfig.showHKCandles = false;
mProviderConfig.xmanConfig.showSMHKCandles = false;
mProviderConfig.xmanConfig.showPeaksAndVales = false;
mProviderConfig.xmanConfig.showTrends = false;
mProviderConfig.xmanConfig.fillTrends = false;
mProviderConfig.xmanConfig.showLevels = false;
mProviderConfig.xmanConfig.showConsolidations = false;
mProviderConfig.xmanConfig.showRibbons = false;
mProviderConfig.xmanConfig.showHull = false;
mProviderConfig.xmanConfig.showSSLChannel = false;
mProviderConfig.xmanConfig.showFibo1Levels = false;
mProviderConfig.xmanConfig.showFibo2Levels = false;
mProviderConfig.xmanConfig.showFibo3Levels = false;
mProviderConfig.xmanConfig.showFibo4Levels = false;
mProviderConfig.xmanConfig.showFibo5Levels = false;
//
PreDefineProviderConfig();
}
//
// Config Representation of X121 Provider Setup ...
// for Specified Strategies ...
void PreDefineProviderConfig()
{
//
// Here we have to Name or Predefined Styles ...
bool x786Config = true;
//
// by default we need to Show Candles and also Candle Timer ...
mProviderConfig.xmanConfig.showCandles = true;
mProviderConfig.xmanConfig.showCandleTimer = true;
//
// now we act based on Predefined Variables ...
if (x786Config)
{
//
bool showHK = false;
bool showPVs = true;
bool showFibo = true;
bool showSMHK = false;
bool showHull = false;
bool showSSLC = false;
bool showTrend = true;
bool showRibbon = true;
bool showPVLevels = false;
bool showPVLevelConsolidations = false;
//
mProviderConfig.xmanConfig.showCandles = !showHK;
mProviderConfig.xmanConfig.showHKCandles = showHK;
mProviderConfig.xmanConfig.showSMHKCandles = showSMHK;
//
mProviderConfig.xmanConfig.showHull = showHull;
mProviderConfig.xmanConfig.showTrends = showTrend;
mProviderConfig.xmanConfig.showRibbons = showRibbon;
mProviderConfig.xmanConfig.showSSLChannel = showSSLC;
//
mProviderConfig.xmanConfig.showFibo1Levels = showFibo;
mProviderConfig.xmanConfig.showFibo2Levels = showFibo;
mProviderConfig.xmanConfig.showFibo3Levels = showFibo;
mProviderConfig.xmanConfig.showFibo4Levels = showFibo;
mProviderConfig.xmanConfig.showFibo5Levels = showFibo;
//
mProviderConfig.xmanConfig.showPeaksAndVales = showPVs;
//
mProviderConfig.xmanConfig.showLevels = showPVLevels;
mProviderConfig.xmanConfig.showConsolidations = showPVLevelConsolidations;
}
}
//
// Check Signallers ...
// when recieved signals we have to check each signal
// based on it's signaller ...
// if there isn't any open Position from it's signaller or
// there was open positions and all of them in profit we accept new recieved signal ...
// in this way we can handle balance between signallers and their positions and also
// we prevent big losses ...
int CheckSignalsProviderState(XSignal &signals[])
{
//
int result = 0;
//
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return result;
}
//
XSignal tmp[];
Copy(
signals,
tmp);
Clean(signals);
//
// Loop through Signals ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = tmp[i];
//
int providersCount = ArraySize(iSignal.providers);
if (providersCount <= 0)
{
continue;
}
//
string iSignaller = iSignal.providers[0];
//
// Retrieve Signaller's Open Positions ...
XPosition iSignallerPositions[];
int iSignallerPositionsCount = GetPositions(
iSignallerPositions,
iSignal.symbol,
iSignal.type,
iSignal.period,
iSignaller);
if (iSignallerPositionsCount <= 0)
{
//
// this means we can accept Signal without Checking anything ...
Add(
iSignal,
signals //
);
//
// TODO: Here we can Provide Support Signals for First Arrived Signal ...
//
continue;
}
else
{
//
// TODO: Remove this ...
// Only One Signal ...
// continue;
}
//
// here we have to check Signallers open Positions Profit ...
double iSignallerPositionsProfit = CalculatePositionsProfit(iSignallerPositions);
bool isInProfit = iSignallerPositionsProfit > 0;
if (!isInProfit)
{
// TODO: Remove this ...
// continue;
}
//
// Check Signal Entry ...
// in Compare with nearest Signaller Position ...
//
// Find Youngest Signaller Position ...
XPosition iSignallerYoungestPosition;
int iSignallerYoungestPositionAge = GetYoungest(
iSignallerYoungestPosition,
iSignallerPositions);
if (iSignallerYoungestPositionAge < 0)
{
// TODO: Remove this ...
// continue;
}
//
bool isEntryOk =
IsLong(iSignal.type) &&
iSignal.type == iSignallerYoungestPosition.type
? iSignal.entry > iSignallerYoungestPosition.entry
: iSignal.entry < iSignallerYoungestPosition.entry;
if (!isEntryOk)
{
// TODO: Remove this ...
// continue;
}
//
// this means all Signaller Open Positions in Profit ...
// so we Accept Signal ...
Add(
iSignal,
signals //
);
}
//
Clean(tmp);
//
result = ArraySize(signals);
//
if (result > 0)
{
//
// This means Signallers provide In Profits Positions Before ...
// the Best thing is make them Risk Free at current Signals Minimum Entry ...
// TODO: Complete This ...
}
//
return result;
}
};
//
// START Usefull Functions ...
//
//
// END Usefull Functions ...
//