1865 lines
50 KiB
Plaintext
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 ...
|
|
//
|