1712 lines
43 KiB
Plaintext
1712 lines
43 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 minProfitPerTrade, // Min Profit Per Trade based On Volume Factor (Hedge)
|
|
double minProfitPerVolumeFactor, // Min Volume Factor for Calculating Profit (Hedge)
|
|
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
|
|
TOnSignalConditions onSignalConditions = NULL // On SignalConditions Event Handler
|
|
) : XSCBaseEA(symbol,
|
|
period,
|
|
magic,
|
|
slippage,
|
|
onStopLossTriggered,
|
|
onTakeProfitTriggered,
|
|
onDealsChangedHandler,
|
|
onOrdersChangedHandler,
|
|
onPositionsChangedHandler,
|
|
onTradeStateChangedHandler)
|
|
{
|
|
//
|
|
mOnSignalConditions = onSignalConditions;
|
|
|
|
//
|
|
mMinProfitPerTrade = minProfitPerTrade;
|
|
mMinProfitPerVolumeFactor = minProfitPerVolumeFactor;
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
HandleEquityManagement();
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Here we Calculate Signals tp/sl volume and etc based on given
|
|
// configurations ...
|
|
PrepareConditionsSignal(iConditions);
|
|
|
|
//
|
|
// Add Signal to Retrieved Signals Collection ...
|
|
Add(
|
|
iConditions.signal,
|
|
signals);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Here we proccess all Exists Registered Providers and get
|
|
// probably signals and add them signals Array ...
|
|
|
|
//
|
|
// Check Signals Exists for Processing ...
|
|
result = ArraySize(signals) > 0;
|
|
|
|
//
|
|
// IMPORTANT:
|
|
// Since we have to Implement our Signal Execution Senario
|
|
// Ignore this here for Default behaviour and implememt or Execution ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Create an Array for Holding Allowed To Execute Signals ...
|
|
// this filled by given Signals from all providers ...
|
|
XSignal allowedSignals[];
|
|
|
|
//
|
|
// Check Account has required Equity for open Trades or not ...
|
|
bool hasEquity = CheckEquityForTrade();
|
|
if (hasEquity)
|
|
{
|
|
//
|
|
// if Equity Exists ...
|
|
|
|
//
|
|
// Check Positions Count ...
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(positions);
|
|
|
|
//
|
|
// Calculate Remained Positions based on configurations ...
|
|
int remainedPositionsCount = mMaxAllowedPositions - positionsCount;
|
|
|
|
//
|
|
int incommingSignalsCount = ArraySize(signals);
|
|
|
|
//
|
|
// Check incomming signals and remained Positions count ...
|
|
if (remainedPositionsCount >= incommingSignalsCount)
|
|
{
|
|
//
|
|
// Since we have necessary Equity for Trade ...
|
|
// and also remainedPositions count is bigger than incomming signals ...
|
|
// Accept all incomming Signals ...
|
|
Copy(
|
|
signals,
|
|
allowedSignals);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// since we have necessary Equity for trade ...
|
|
// but incomming Signals count is bigger than Max allowed positions at same time ...
|
|
// we have to select only remains count ...
|
|
for (int i = 0; i < remainedPositionsCount; i++)
|
|
{
|
|
//
|
|
XSignal iSignal = signals[i];
|
|
|
|
//
|
|
Add(
|
|
iSignal,
|
|
allowedSignals);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// there isn't enough Equity for Trade ...
|
|
// How to Select Signals when there is no Equity for Trade ...
|
|
|
|
//
|
|
// TODO: we can Implement Equity Management here ...
|
|
|
|
//
|
|
LogMessage("No Equity ...");
|
|
}
|
|
|
|
//
|
|
// Check Allowed Signals Count ...
|
|
int allowedSignalsCount = ArraySize(allowedSignals);
|
|
if (allowedSignalsCount > 0)
|
|
{
|
|
//
|
|
// Prepare Allowed Signals for Execution ...
|
|
PrepareSignals(allowedSignals);
|
|
|
|
//
|
|
// Execute Signals oly when allowed ...
|
|
int executed = mTrader.ExecuteSignals(allowedSignals);
|
|
if (executed > 0)
|
|
{
|
|
//
|
|
// Draw Signal ...
|
|
// On Chart ...
|
|
DrawSignals(
|
|
allowedSignals,
|
|
true);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Prevent Default Base Signal Execution ...
|
|
|
|
//
|
|
Clean(signals);
|
|
|
|
//
|
|
return false;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Inheritance Functions ...
|
|
//
|
|
|
|
//
|
|
// START Provided Actions ...
|
|
//
|
|
|
|
//
|
|
// END Provided Actions ...
|
|
//
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
X121SignalProvider mProviders[];
|
|
X121ProviderInputs mProviderConfig;
|
|
TOnSignalConditions mOnSignalConditions;
|
|
|
|
//
|
|
double mMinProfitPerTrade;
|
|
double mMinProfitPerVolumeFactor;
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
//
|
|
// Pepare a Collection Of Signals ...
|
|
void PrepareSignals(XSignal &signals[])
|
|
{
|
|
//
|
|
int signalsCount = ArraySize(signals);
|
|
if (signalsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < signalsCount; i++)
|
|
{
|
|
//
|
|
PrepareSignal(signals[i]);
|
|
}
|
|
}
|
|
|
|
//
|
|
// POSITIONPACK ...
|
|
|
|
//
|
|
// Check a Position Pack is Ready for Hedging ...
|
|
bool IsReadyForEQMHedge(XPositionPack &pack)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (mMinProfitPerTrade <= 0 ||
|
|
mMinProfitPerVolumeFactor <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (pack.supportPositionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double profit = pack.position.profit;
|
|
double requiredProfit =
|
|
((pack.position.volume / mMinProfitPerVolumeFactor) *
|
|
mMinProfitPerTrade) +
|
|
(-1 * pack.position.swap);
|
|
|
|
//
|
|
for (int i = 0; i < pack.supportPositionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = pack.supportPositions[i];
|
|
|
|
//
|
|
profit += iPosition.profit;
|
|
requiredProfit +=
|
|
((iPosition.volume / mMinProfitPerVolumeFactor) *
|
|
mMinProfitPerTrade) +
|
|
(-1 * iPosition.swap);
|
|
}
|
|
|
|
//
|
|
result = profit >= requiredProfit;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Close a Position Pack and Cancel All of it's Supports ...
|
|
bool HandleClosePack(XPositionPack &pack)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (pack.ticket <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOrder orders[];
|
|
XPosition positions[];
|
|
|
|
//
|
|
bool hasPos = pack.position.ticket > 0;
|
|
if (hasPos)
|
|
{
|
|
Add(
|
|
pack.position,
|
|
positions);
|
|
}
|
|
|
|
//
|
|
bool hasSupportPos = pack.supportPositionsCount > 0;
|
|
if (hasSupportPos)
|
|
{
|
|
//
|
|
Copy(
|
|
pack.supportPositions,
|
|
positions,
|
|
false);
|
|
}
|
|
|
|
//
|
|
bool hasSupportOrd = pack.supportOrdersCount > 0;
|
|
if (hasSupportOrd)
|
|
{
|
|
//
|
|
Copy(
|
|
pack.supportOrders,
|
|
orders);
|
|
}
|
|
|
|
//
|
|
string comment = "EQM Close Pack";
|
|
|
|
//
|
|
int closed = mTrader.ClosePositions(positions, comment);
|
|
int canceled = mTrader.CancelOrders(orders);
|
|
|
|
//
|
|
result = closed + canceled == ArraySize(orders) + ArraySize(positions);
|
|
if (result)
|
|
{
|
|
//
|
|
string message = "EQM Close Position(" + ToString(pack.ticket) + ")'s Pack ...";
|
|
|
|
//
|
|
LogMessage(message);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// POSITIONMANAGEMENT ...
|
|
//
|
|
|
|
//
|
|
// Calculate Positions Profit Summary ...
|
|
double CalculatePositionsProfit(
|
|
XPosition &positions[] // Source
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
int positionsCount = ArraySize(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
result += iPosition.profit;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Required Profit for Hedging ...
|
|
double CalculateRequiredProfitForHedge(
|
|
XPosition &positions[] // Source
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
int positionsCount = ArraySize(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
result +=
|
|
((iPosition.volume / mMinProfitPerVolumeFactor) *
|
|
mMinProfitPerTrade) +
|
|
(-1 * iPosition.swap);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Manage Positions ...
|
|
void HandlePositionManagement()
|
|
{
|
|
//
|
|
// HandleHedgePositionPacks();
|
|
|
|
//
|
|
// HandleHedgePositions();
|
|
|
|
//
|
|
HandleCloseOrTrailStopMinProfitPositions();
|
|
}
|
|
|
|
//
|
|
void HandleHedgePositions()
|
|
{
|
|
//
|
|
bool isReady = IsPositionsReadyForEQMHedge();
|
|
if (!isReady)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(positions);
|
|
|
|
//
|
|
string comment = "EQM Hedge Positions ...";
|
|
|
|
//
|
|
int closed = mTrader.ClosePositions(
|
|
positions,
|
|
comment);
|
|
bool isClosed = closed == positionsCount;
|
|
if (isClosed)
|
|
{
|
|
//
|
|
LogMessage(comment);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close a Position Pack Wen Reached to Specific Profit ...
|
|
void HandleHedgePositionPacks()
|
|
{
|
|
//
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
XPositionPack iPack;
|
|
bool hasPack = mTrader.GetPositionPack(
|
|
iPosition.ticket,
|
|
iPosition.symbol,
|
|
iPosition.period,
|
|
iPack);
|
|
if (!hasPack)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Pack for Open Positions ...
|
|
bool isValidPack = iPack.supportPositionsCount > 0;
|
|
if (!isValidPack)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// we sure a Position has Support and it's support open ...
|
|
bool isReady = IsReadyForEQMHedge(iPack);
|
|
if (!isReady)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isClosed = HandleClosePack(iPack);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Try to Trail StopLoss or Close Posititons
|
|
// when reached Min Profit ...
|
|
void HandleCloseOrTrailStopMinProfitPositions()
|
|
{
|
|
//
|
|
// Retrieve In Profit Positions ...
|
|
XPosition positions[];
|
|
int positionsCount = GetInProfitPositions(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
// Now we have to Calculate min Profit ...
|
|
double requiredProfit =
|
|
((iPosition.volume / mMinProfitPerVolumeFactor) *
|
|
mMinProfitPerTrade) +
|
|
(-1 * iPosition.swap);
|
|
|
|
//
|
|
// Now we Have to Check if Trailed Before or not ...
|
|
int trailLevel = ExtractSLTrailLevel(iPosition.comment);
|
|
if (trailLevel > 0)
|
|
{
|
|
requiredProfit *= (trailLevel + 1);
|
|
}
|
|
|
|
//
|
|
// Check Can Trail or Close on Min Profit ...
|
|
bool conditionsPassed = iPosition.profit >= requiredProfit;
|
|
if (!conditionsPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Now we have Sure iPosition is Ready for Trailing Stop or Close on Min Profit ...
|
|
bool isLong = IsLong(iPosition.type);
|
|
|
|
//
|
|
// CASE A try to Trail Stop ...
|
|
double sl = 0;
|
|
double distance = 0;
|
|
if ((isLong && (iPosition.price > iPosition.entry &&
|
|
iPosition.entry > iPosition.sl)) ||
|
|
(!isLong && (iPosition.price < iPosition.entry &&
|
|
iPosition.entry < iPosition.sl)))
|
|
{
|
|
//
|
|
// First Trail ...
|
|
|
|
//
|
|
distance = isLong
|
|
? iPosition.price - iPosition.entry
|
|
: iPosition.entry - iPosition.price;
|
|
|
|
//
|
|
sl = iPosition.entry;
|
|
}
|
|
else if ((isLong && (iPosition.price > iPosition.sl &&
|
|
iPosition.entry <= iPosition.sl)) ||
|
|
(!isLong && (iPosition.price < iPosition.sl &&
|
|
iPosition.entry >= iPosition.sl)))
|
|
{
|
|
//
|
|
// Trailed Before ...
|
|
|
|
//
|
|
distance = isLong
|
|
? iPosition.price - iPosition.entry
|
|
: iPosition.entry - iPosition.price;
|
|
|
|
//
|
|
sl = isLong
|
|
? iPosition.sl + distance
|
|
: iPosition.sl - distance;
|
|
}
|
|
|
|
//
|
|
// Check Main Selected Position is Support of another Position or not ...
|
|
string params[];
|
|
bool isSupport = ExtractSupportParams(
|
|
iPosition.comment,
|
|
params);
|
|
|
|
//
|
|
bool isTrailed = false;
|
|
bool canTrail = !isSupport && sl > 0 && distance > 0;
|
|
if (canTrail)
|
|
{
|
|
//
|
|
string comment = PrepareSLTrailComment(iPosition.comment);
|
|
|
|
//
|
|
isTrailed = mTrader.Modify(
|
|
iPosition.ticket,
|
|
sl,
|
|
iPosition.tp);
|
|
}
|
|
if (isTrailed)
|
|
{
|
|
//
|
|
string message = "EQM Trail Position(" + ToString(iPosition.ticket) + ")'s Stop Loss ...";
|
|
|
|
//
|
|
LogMessage(message);
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// CASE B if not Trail, Close it in Min Profit ...
|
|
string comment = "EQM Close Min Profit ...";
|
|
|
|
//
|
|
// Check Position has Pack Or Not ...
|
|
// if has Pack must Close Pack ...
|
|
// if not, Close position itself ...
|
|
XPositionPack iPack;
|
|
bool hasPack = mTrader.GetPositionPack(
|
|
iPosition.ticket,
|
|
iPosition.symbol,
|
|
iPosition.period,
|
|
iPack);
|
|
if (hasPack)
|
|
{
|
|
//
|
|
HandleClosePack(iPack);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
if (!isSupport)
|
|
{
|
|
//
|
|
bool isClosed = mTrader.Close(
|
|
iPosition.ticket,
|
|
comment);
|
|
if (isClosed)
|
|
{
|
|
//
|
|
string message = "EQM Close Position(" + ToString(iPosition.ticket) + ") In Min Profit: " + ToString(iPosition.profit);
|
|
|
|
//
|
|
LogMessage(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Positions is Ready fro Hedging ...
|
|
bool IsPositionsReadyForEQMHedge()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (mMinProfitPerTrade <= 0 ||
|
|
mMinProfitPerVolumeFactor <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double profit = 0;
|
|
double requiredProfit = 0;
|
|
|
|
//
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(positions);
|
|
if (positionsCount <= 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
profit = CalculatePositionsProfit(positions);
|
|
requiredProfit = CalculateRequiredProfitForHedge(positions);
|
|
|
|
//
|
|
result = profit >= requiredProfit;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// EQUITYMANAGEMENT ...
|
|
//
|
|
|
|
//
|
|
// All available Equity Actions Implemented here ...
|
|
void HandleEquityManagement()
|
|
{
|
|
//
|
|
// TODO: Complete this ...
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Generate EQM Support Signals ...
|
|
int GenerateEQMSupports(
|
|
XSignal &supports[] // Holds Supports
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Clean result Array ...
|
|
Clean(supports);
|
|
|
|
//
|
|
// Since we Generate Support Signals based on Max In Drawdown Positions ...
|
|
// we hae to Find it and then find it's Related Provider ...
|
|
// then recieve Market Conditions based on it's Signaller's Provider ...
|
|
// then try to Generate Supports ...
|
|
XPosition inDrawdownPositions[];
|
|
int inDrawdownPositionsCount = GetInDrawdownPositions(
|
|
inDrawdownPositions,
|
|
NULL, // All Symbols ...
|
|
NULL, // All TYpe Of Positions ...
|
|
NULL, // All Periods ...
|
|
NULL, // All Providers ...
|
|
X_POSITION_SELECT_MAX // we need Max InDrawdown ...
|
|
);
|
|
if (inDrawdownPositionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Since We Select Max here ...
|
|
// and also check count ...
|
|
// just Recieve Max In DD Position ...
|
|
XPosition maxInDDPosition = inDrawdownPositions[0];
|
|
|
|
//
|
|
// Here we can Select Provider based on InDD Position ...
|
|
int providerIDX = GetProviderIndex(
|
|
maxInDDPosition.symbol,
|
|
maxInDDPosition.period);
|
|
|
|
//
|
|
// Validate Index ...
|
|
if (providerIDX <= -1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Market Conditions Based on Specific Provider ...
|
|
X121MarketConditions conditions = mProviders[providerIDX]
|
|
.provider
|
|
.GetMarketConditions(0);
|
|
|
|
//
|
|
// Here we have multiple Senarios for Supporting ...
|
|
|
|
//
|
|
// Support Using Peaks and Vales ...
|
|
// in this Senario we Place Two Order on Peaks and Vales ...
|
|
|
|
//
|
|
// Peaks ...
|
|
XSignal pSignal;
|
|
// TODO: Implwmwnr this ...
|
|
|
|
//
|
|
// Vales ...
|
|
XSignal vSignal;
|
|
// TODO: Implwmwnr this ...
|
|
|
|
//
|
|
result = ArraySize(supports);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Count all open Positions Volume for supports ...
|
|
double GetEQMSupportVolume()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Retrieve Positions ...
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve EQM Positions and Check ...
|
|
// if it's count bigger than 0 means there are an Open
|
|
// EQM Support Position and we do not have to do anything ...
|
|
XPosition eqmPositions[];
|
|
int eqmPositionsCount = GetEQMPositions(eqmPositions);
|
|
if (eqmPositionsCount > 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
result += iPosition.volume;
|
|
}
|
|
|
|
//
|
|
// Multiply Volume Summary ...
|
|
// TODO: Make it Configurable ...
|
|
result *= 1.5;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Account is Ready for EQM Hedge or not ...
|
|
bool IsReadyForEQMHedge()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check required Inputs ...
|
|
if (mMinProfitPerTrade <= 0 ||
|
|
mMinProfitPerVolumeFactor <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check at least One EQM Support Position must be Open ...
|
|
XPosition eqmPositions[];
|
|
int eqmPositionsCount = GetEQMPositions(eqmPositions);
|
|
if (eqmPositionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get All Open Positions for Calculate Account Profit ...
|
|
XPosition positions[];
|
|
int positionsCount = GetPositions(
|
|
positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Factor Variables ...
|
|
double profit = 0;
|
|
double requiredProfit = 0;
|
|
|
|
//
|
|
// Calculate Account Profit Factors ...
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
profit += iPosition.profit;
|
|
requiredProfit +=
|
|
((iPosition.volume / mMinProfitPerVolumeFactor) *
|
|
mMinProfitPerTrade) +
|
|
(-1 * iPosition.swap);
|
|
}
|
|
|
|
//
|
|
// Calculate the result ...
|
|
result = profit >= requiredProfit;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// PROVIDERS ...
|
|
//
|
|
|
|
//
|
|
// 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;
|
|
mProviderConfig.xmanConfig.trendPriceAppliedTo = PRICE_MEDIAN;
|
|
|
|
//
|
|
// Ribbon Detection ...
|
|
mProviderConfig.xmanConfig.ribbonMode = X_MA_AMA;
|
|
|
|
//
|
|
// 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 = true;
|
|
bool showPVs = true;
|
|
bool showFibo = true;
|
|
bool showHull = false;
|
|
bool showSSLC = false;
|
|
bool showTrend = true;
|
|
bool showRibbon = false;
|
|
bool showPVLevels = false;
|
|
bool showPVLevelConsolidations = false;
|
|
|
|
//
|
|
mProviderConfig.xmanConfig.showCandles = !showHK;
|
|
mProviderConfig.xmanConfig.showHKCandles = showHK;
|
|
mProviderConfig.xmanConfig.showSMHKCandles = showHK;
|
|
|
|
//
|
|
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;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Prepare Signal ...
|
|
void PrepareConditionsSignal(X121MarketConditions &conditions)
|
|
{
|
|
//
|
|
if (!conditions.hasSignal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isLong = IsLong(conditions.signal.type);
|
|
|
|
//
|
|
// Check Calculate TP ...
|
|
if (
|
|
conditions.signal.sl > 0 &&
|
|
conditions.signal.r2r > 0 &&
|
|
conditions.signal.entry > 0 &&
|
|
conditions.signal.calculateTP)
|
|
{
|
|
//
|
|
double riskPrice = MathAbs(conditions.signal.entry - conditions.signal.sl);
|
|
double riskPoint = PriceToPoint(
|
|
conditions.signal.symbol,
|
|
riskPrice);
|
|
double rewardPoint = riskPoint * conditions.signal.r2r;
|
|
double rewardPrice = PointToPrice(
|
|
conditions.signal.symbol,
|
|
rewardPoint);
|
|
|
|
//
|
|
double tp =
|
|
isLong
|
|
? conditions.signal.entry + rewardPrice
|
|
: conditions.signal.entry - rewardPrice;
|
|
|
|
//
|
|
conditions.signal.tp = tp;
|
|
}
|
|
|
|
//
|
|
PrepareSignal(conditions.signal);
|
|
|
|
//
|
|
conditions.signal.supportAndResistance = conditions.supportResistances;
|
|
}
|
|
|
|
//
|
|
// TODO: Delete This ...
|
|
void DrawConditionsSignalOnChart(X121MarketConditions &conditions)
|
|
{
|
|
//
|
|
ulong mTicket = MathRand() * 100000;
|
|
|
|
//
|
|
DrawSignal(
|
|
mTicket,
|
|
conditions.signal);
|
|
|
|
//
|
|
DrawSupportResistance(
|
|
0,
|
|
conditions.supportResistances,
|
|
conditions.signal.providers[0]);
|
|
}
|
|
};
|
|
|
|
//
|
|
// START Usefull Functions ...
|
|
//
|
|
|
|
//
|
|
// END Usefull Functions ...
|
|
//
|