1360 lines
32 KiB
Plaintext
1360 lines
32 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Expert Advisor
|
|
// ----------------------------------------
|
|
// Name: X121EA
|
|
// Description: this is an expert controller
|
|
// advisors which provides a mechanism for use them ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm X121EA"
|
|
#property strict
|
|
|
|
//
|
|
// START Definitions ...
|
|
//
|
|
|
|
//
|
|
// Common Library ...
|
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
|
|
|
//
|
|
// Alert Library ...
|
|
#include "../Libraries/x-saherelm.alert.lib.mq5"
|
|
|
|
//
|
|
// Draw Library ...
|
|
#include "../Libraries/x-saherelm.draw.lib.mq5"
|
|
|
|
//
|
|
// Account Class ...
|
|
#include "../Classes/x-saherelm.xaccount.class.mq5"
|
|
|
|
//
|
|
// Trade Class ...
|
|
#include "../Classes/x-saherelm.xtrade.class.mq5"
|
|
|
|
//
|
|
// Signal Provider Class Library ...
|
|
#include "../Providers/x.saherelm.x121.provider.mq5"
|
|
|
|
//
|
|
// Draw Library ...
|
|
#include "../Libraries/x-saherelm.x121.draw.lib.mq5"
|
|
|
|
//
|
|
#define ShortName "X121EA"
|
|
|
|
//
|
|
// Convert Position to Signal ...
|
|
XSignal ToSignalInfo(
|
|
XPosition &position)
|
|
{
|
|
//
|
|
XSignal result;
|
|
|
|
//
|
|
result.tp = position.tp;
|
|
result.sl = position.sl;
|
|
result.type = position.type;
|
|
result.entry = position.entry;
|
|
result.symbol = position.symbol;
|
|
result.period = position.period;
|
|
result.volume = position.volume;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Definitions ...
|
|
//
|
|
|
|
//
|
|
// START Inputs ...
|
|
//
|
|
|
|
//
|
|
// EA ...
|
|
input group "Common";
|
|
input bool xEAEnable = true; // Enable EA
|
|
input int xEASlippage = 10; // Slippgae
|
|
input ulong xEAMagicNumber = 1604056; // Magic Number
|
|
|
|
//
|
|
// Signals ...
|
|
input group "Signals";
|
|
input bool xEAEnableLongs = true; // Enable Long Trades
|
|
input bool xEAEnableShorts = true; // Enable Short Trades
|
|
|
|
//
|
|
// Risk Management ...
|
|
input group "Risk Management";
|
|
input int xEAMaxOpenPositions = 15; // Max Allowed Open Positions
|
|
input double xEAMaxAllowedDrawDownFactor = 0.15; // Max Allowed Drawdown Factor
|
|
// input double xEAMinProfitPerOpenPositionForHedging = 0.9; // Close All Positions Fctor
|
|
|
|
//
|
|
// Alerts ...
|
|
input group "Alerts";
|
|
input bool xEAEnableAlerts = true; // Enable Events Alert
|
|
input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour
|
|
input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day
|
|
input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week
|
|
input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month
|
|
|
|
//
|
|
// END Inputs ...
|
|
//
|
|
|
|
//
|
|
// START Including Providers ...
|
|
//
|
|
|
|
//
|
|
// Logger Library ...
|
|
#include "../Libraries/x-saherelm.log.lib.mq5"
|
|
|
|
//
|
|
// END Including Providers ...
|
|
//
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
bool isXEANewHour;
|
|
bool isXEANewDay;
|
|
bool isXEANewWeek;
|
|
bool isXEANewMonth;
|
|
|
|
//
|
|
// Determines EA is Running On Test Mode or not ...
|
|
bool xEAIsTestMode = false;
|
|
|
|
//
|
|
// Check prevent Double Signalling on Same Candle ...
|
|
bool xEAWaitUntilNextCandle = false;
|
|
|
|
//
|
|
XSCTrade *xEATrade;
|
|
XSCAccount *xEAAccount;
|
|
XSCX121Provider *xEAProvider;
|
|
// X121SignalProvider xEAProviders[];
|
|
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// START Event Handlers ...
|
|
//
|
|
|
|
//
|
|
// Initialization ...
|
|
int OnInit()
|
|
{
|
|
//
|
|
logTag = ShortName;
|
|
drawPrefix = logTag;
|
|
alertPrefix = logTag;
|
|
|
|
//
|
|
// Reset Timings ...
|
|
ResetTiming();
|
|
|
|
//
|
|
// Validate Inputs ...
|
|
if (!ValidateInputs())
|
|
{
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
// Initialize X121EA Providers ...
|
|
if (!InitializeProviders())
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
// Init Succeed ...
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//
|
|
// DeInitialization ...
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//
|
|
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
|
|
// REASON_REMOVE 1 Program removed from a chart
|
|
// REASON_RECOMPILE 2 Program recompiled
|
|
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
|
|
// REASON_CHARTCLOSE 4 Chart closed
|
|
// REASON_PARAMETERS 5 Inputs changed by a user
|
|
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
|
|
// REASON_TEMPLATE 7 Another chart template applied
|
|
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
|
|
// REASON_CLOSE 9 Terminal closed
|
|
|
|
//
|
|
// Here we can handle De Initialization Reasons ...
|
|
delete xEATrade;
|
|
delete xEAAccount;
|
|
delete xEAProvider;
|
|
|
|
//
|
|
// De Initialize XEA Providers ...
|
|
}
|
|
|
|
//
|
|
// On Tick Handler ...
|
|
void OnTick()
|
|
{
|
|
//
|
|
// Handle Monthly Alert ...
|
|
bool isFirstMonth = xMonth == -1;
|
|
isXEANewMonth = IsNewMonth();
|
|
bool canMonthlyAlert =
|
|
isXEANewMonth &&
|
|
xEAEnableAlerts &&
|
|
xEAEnableMonthlyAlerts;
|
|
if (canMonthlyAlert)
|
|
{
|
|
//
|
|
string message = "New Month ...";
|
|
|
|
//
|
|
SendAlert(message);
|
|
}
|
|
|
|
//
|
|
// Handle Weekly Alert ...
|
|
bool isFirstWeek = xDayOfWeek == -1;
|
|
isXEANewWeek = IsNewWeek();
|
|
bool canWeeklyAlert =
|
|
isXEANewWeek &&
|
|
xEAEnableAlerts &&
|
|
xEAEnableWeeklyAlerts;
|
|
if (canWeeklyAlert)
|
|
{
|
|
//
|
|
string message = "New Week ...";
|
|
|
|
//
|
|
SendAlert(message);
|
|
}
|
|
|
|
//
|
|
// Handle Daily Alert ...
|
|
bool isFirstDay = xDay == -1;
|
|
isXEANewDay = IsNewDay();
|
|
bool canDailyAlert =
|
|
isXEANewDay &&
|
|
xEAEnableAlerts &&
|
|
xEAEnableDailyAlerts;
|
|
if (canDailyAlert)
|
|
{
|
|
//
|
|
string message = "New Day ...";
|
|
|
|
//
|
|
SendAlert(message);
|
|
}
|
|
|
|
//
|
|
// Handle Hourly Alert ...
|
|
bool isFirstHour = xHour == -1;
|
|
isXEANewHour = IsNewHour();
|
|
bool canHourlyAlert =
|
|
isXEANewHour &&
|
|
xEAEnableAlerts &&
|
|
xEAEnableHourlyAlerts;
|
|
if (canHourlyAlert)
|
|
{
|
|
//
|
|
string message = "New Hour ...";
|
|
|
|
//
|
|
SendAlert(message);
|
|
}
|
|
|
|
//
|
|
// Handle Guarding Strategies ...
|
|
HandleGuard();
|
|
|
|
//
|
|
// Prevent Going Forward if user Disable it ...
|
|
if (xEAEnable)
|
|
{
|
|
//
|
|
// TODO: Remove this due test ...
|
|
// if (IsRunningOnTestMode())
|
|
// {
|
|
// xEATrade.
|
|
// }
|
|
|
|
//
|
|
// Call All Providers OnTick Method ...
|
|
CallProvidersOnTick();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Trade Events ...
|
|
void OnTrade()
|
|
{
|
|
//
|
|
// Handle Trading State ...
|
|
xEATrade.HandleOnTrade();
|
|
}
|
|
|
|
//
|
|
// Chart Events Handling ...
|
|
void OnChartEvent(
|
|
const int id, // event ID
|
|
const long &lparam, // long type event parameter
|
|
const double &dparam, // double type event parameter
|
|
const string &sparam // string type event parameter
|
|
)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Handle Signal Event ...
|
|
void OnSignalConditionsRecieved(X121MarketConditions &info)
|
|
{
|
|
//
|
|
if (!info.hasSignal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Diable Trading if a Direction is Disabled ...
|
|
if ((info.signal.type == POSITION_TYPE_BUY && !xEAEnableLongs) ||
|
|
(info.signal.type != POSITION_TYPE_SELL && !xEAEnableShorts))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Count Open Positions ...
|
|
int openPositionsCount = xEATrade.PositionsCount();
|
|
if (xEAMaxOpenPositions > 0 &&
|
|
openPositionsCount >= xEAMaxOpenPositions)
|
|
{
|
|
//
|
|
string msg = "Max Allowed Positions Reached, Ignore Trading ...";
|
|
LogMessage(msg);
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Tradable Balance ...
|
|
double availableBalance = xEAAccount.GetEquity();
|
|
|
|
//
|
|
// Verify Available Balance ...
|
|
double balance = xEAAccount.GetBalance();
|
|
|
|
//
|
|
double forCalculationBalance = MathMax(balance, availableBalance);
|
|
double forTradeBalance = MathMin(balance, availableBalance);
|
|
double mustHaveBalanceForTrading = forCalculationBalance * xEAMaxAllowedDrawDownFactor;
|
|
if (availableBalance < mustHaveBalanceForTrading)
|
|
{
|
|
//
|
|
string msg = "Max Allowed Equity for Trading Reached, Ignore Trading ...";
|
|
LogMessage(msg);
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Here i Must Calculate TP and SL based on R2R and riskable Factor ...
|
|
bool isLong = IsLong(info.signal.type);
|
|
|
|
//
|
|
// Check Order Mode ...
|
|
if (info.signal.mode == NULL)
|
|
{
|
|
//
|
|
// Set Market Execution as Default ...
|
|
info.signal.mode = X_ORDER_MODE_MARKET;
|
|
}
|
|
|
|
//
|
|
bool isMarketMode = info.signal.mode == X_ORDER_MODE_MARKET;
|
|
|
|
//
|
|
// Calculate Entry Price ...
|
|
if (info.signal.entry <= 0)
|
|
{
|
|
//
|
|
info.signal.entry = GetEntry(
|
|
info.signal.symbol,
|
|
info.signal.type);
|
|
}
|
|
|
|
//
|
|
// Calculate TP and SL ...
|
|
double mPoint = GetPoints(info.signal.symbol);
|
|
|
|
//
|
|
// Normalize SL Price ...
|
|
if (info.signal.sl > 0)
|
|
{
|
|
info.signal.sl = NormalizePrice(info.signal.sl, info.signal.symbol);
|
|
}
|
|
|
|
//
|
|
// Retrieve Symbol Point Value ...
|
|
double pointValue = xEAAccount.GetPointValue(info.signal.symbol);
|
|
|
|
//
|
|
// Calculate Risk ...
|
|
double riskPrice = MathAbs(info.signal.entry - info.signal.sl);
|
|
riskPrice = NormalizePrice(riskPrice, info.signal.symbol);
|
|
|
|
//
|
|
double riskPoints = PriceToPoint(riskPrice);
|
|
riskPoints = NormalizeDouble(riskPoints, 0);
|
|
|
|
//
|
|
// Calculating Reward based On Ratio ...
|
|
double rewardPoints = riskPoints * info.signal.r2r;
|
|
double rewardPrice = PointToPrice(rewardPoints);
|
|
rewardPrice = NormalizePrice(rewardPrice, info.signal.symbol);
|
|
|
|
//
|
|
// Calculate TP Price ...
|
|
double tpValue = isLong
|
|
? info.signal.entry + rewardPrice
|
|
: info.signal.entry - rewardPrice;
|
|
|
|
//
|
|
// Calculate SL Price ...
|
|
double slValue = isLong
|
|
? info.signal.entry - riskPrice
|
|
: info.signal.entry + riskPrice;
|
|
|
|
//
|
|
// Balance Amount which we risks on each Provider's Trade ...
|
|
double amount = availableBalance * info.signal.riskAmount;
|
|
|
|
//
|
|
// Calculating Trade Volume based on risk Points and Amount ...
|
|
double volume =
|
|
info.signal.useRiskAmountAsVolume
|
|
? info.signal.riskAmount
|
|
: xEAAccount.CalculateVolume(
|
|
info.signal.symbol,
|
|
amount,
|
|
riskPoints);
|
|
volume = NormalizeVolume(volume, info.signal.symbol);
|
|
|
|
//
|
|
// Set Caculated TP, SL and Volume ...
|
|
if (info.signal.calculateTP)
|
|
{
|
|
//
|
|
if (info.signal.useSupportAndResistance)
|
|
{
|
|
//
|
|
double mTmp[];
|
|
double mTmpPrice;
|
|
LogMessage("MomentumStep: " + (string)info.momentumStep);
|
|
|
|
//
|
|
// Find Good Entry Points ...
|
|
if (!isMarketMode)
|
|
{
|
|
//
|
|
if (isLong)
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.res);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.sup);
|
|
}
|
|
|
|
//
|
|
mTmpPrice =
|
|
isLong
|
|
? info.signal.entry + info.momentumStep
|
|
: info.signal.entry - info.momentumStep;
|
|
double entry =
|
|
FindLesserThanValue(
|
|
mTmpPrice,
|
|
mTmp,
|
|
!isLong);
|
|
Clean(mTmp);
|
|
|
|
//
|
|
info.signal.entry = entry;
|
|
}
|
|
|
|
//
|
|
// Find Good SL Point ...
|
|
|
|
//
|
|
if (isLong)
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.sup);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.res);
|
|
}
|
|
|
|
//
|
|
mTmpPrice =
|
|
isLong
|
|
? info.signal.entry - info.momentumStep
|
|
: info.signal.entry + info.momentumStep;
|
|
double sl =
|
|
FindBiggerThanValue(
|
|
mTmpPrice,
|
|
mTmp,
|
|
!isLong);
|
|
Clean(mTmp);
|
|
|
|
//
|
|
info.signal.sl = sl;
|
|
|
|
//
|
|
// Find Good TP Point ...
|
|
|
|
//
|
|
if (isLong)
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.res);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ArrayCopy(
|
|
mTmp,
|
|
info.supportResistances.sup);
|
|
}
|
|
|
|
//
|
|
// Risk Price ...
|
|
mTmpPrice = MathAbs(info.signal.entry - info.signal.sl);
|
|
|
|
//
|
|
// Reward Price ...
|
|
mTmpPrice *= info.signal.r2r;
|
|
|
|
//
|
|
// Start Search TP ...
|
|
mTmpPrice = isLong
|
|
? info.signal.entry + mTmpPrice
|
|
: info.signal.entry - mTmpPrice;
|
|
double tp =
|
|
FindLesserThanValue(
|
|
mTmpPrice,
|
|
mTmp,
|
|
!isLong);
|
|
Clean(mTmp);
|
|
|
|
//
|
|
info.signal.tp = tp;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
info.signal.tp = tpValue;
|
|
info.signal.sl = slValue;
|
|
}
|
|
}
|
|
|
|
//
|
|
info.signal.volume = volume;
|
|
|
|
//
|
|
string comment = GenerateProvidersString(info.signal);
|
|
|
|
//
|
|
// TODO: Remove this ...
|
|
ulong mTicket = MathRand() * 100000;
|
|
DrawSignal(
|
|
mTicket,
|
|
info.signal);
|
|
|
|
//
|
|
DrawSupportResistance(
|
|
0,
|
|
info.supportResistances,
|
|
info.signal.providers[0]);
|
|
|
|
//
|
|
return;
|
|
|
|
//
|
|
// Here We Execute the Signal by Trader Class Instance ...
|
|
bool isPositionExecuted = xEATrade.ExecuteSignal(
|
|
info.signal,
|
|
comment);
|
|
|
|
//
|
|
if (isPositionExecuted)
|
|
{
|
|
//
|
|
// Retrieve Position Ticket ...
|
|
ulong ticket = 0;
|
|
bool isMarketMode = info.signal.mode == X_ORDER_MODE_MARKET;
|
|
if (isMarketMode)
|
|
{
|
|
ticket = xEATrade.GetLastOpenPositionTicket();
|
|
}
|
|
else
|
|
{
|
|
ticket = xEATrade.GetLastPlacedOrderTicket();
|
|
}
|
|
|
|
if (ticket == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Draw Signal ...
|
|
DrawSignal(ticket, info.signal);
|
|
|
|
//
|
|
// Alert Position ...
|
|
string msg =
|
|
(isMarketMode
|
|
? "Position"
|
|
: "Order") +
|
|
": " + (string)ticket + " was " + (isMarketMode ? "Opened" : "Placed") + " ...";
|
|
LogMessage(msg);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle StopLoss Event ...
|
|
void OnStopLossTriggered(const XDeal &deal)
|
|
{
|
|
//
|
|
string msg = "SL: " + (string)deal.positionId;
|
|
LogMessage(msg);
|
|
}
|
|
|
|
//
|
|
// Handle TakeProfit Event ...
|
|
void OnTakeProfitTriggered(const XDeal &deal)
|
|
{
|
|
//
|
|
string msg = "TP: " + (string)deal.positionId;
|
|
LogMessage(msg);
|
|
}
|
|
|
|
//
|
|
// Handle Deals Changed Event ...
|
|
void OnDealsChangedHandler(int count)
|
|
{
|
|
//
|
|
// string msg = "Deals Changed: " + (string)count;
|
|
// LogMessage(msg);
|
|
}
|
|
|
|
//
|
|
// Handle Order Changed Event ...
|
|
void OnOrdersChangedHandler(int count)
|
|
{
|
|
//
|
|
// string msg = "Orders Changed: " + (string)count;
|
|
// LogMessage(msg);
|
|
}
|
|
|
|
//
|
|
// Handle Position Changed Event ...
|
|
void OnPositionsChangedHandler(int count)
|
|
{
|
|
// //
|
|
// int positionsCount = xEATrade.PositionsCount();
|
|
// if (count <= 0 || positionsCount <= 0)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// XPosition positions[];
|
|
// xEATrade.GetPositions(positions);
|
|
// for (int i = 0; i < positionsCount; i++)
|
|
// {
|
|
// //
|
|
// XPosition iPosition = positions[i];
|
|
|
|
// //
|
|
// bool isIPositionHasSupport =
|
|
// xEATrade.HasSupport(iPosition.ticket);
|
|
// if (isIPositionHasSupport)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// double sl = iPosition.sl;
|
|
|
|
// //
|
|
// XSignal signal;
|
|
// bool isGenerated = xEATrade.GenerateSLSupportSignal(
|
|
// signal,
|
|
// iPosition.ticket);
|
|
// if (!isGenerated)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// string comment = GenerateSupportSignalComment(iPosition.ticket);
|
|
|
|
// //
|
|
// bool isExecuted = xEATrade.ExecuteSignal(
|
|
// signal,
|
|
// comment);
|
|
// if (!isExecuted)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //
|
|
// // Now we have to Disable Position SL ...
|
|
// bool isModified = xEATrade.Modify(
|
|
// iPosition.ticket,
|
|
// 0,
|
|
// iPosition.tp,
|
|
// iPosition.comment);
|
|
// if (!isModified)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// string msg = "Execute SL Support Signal for Position (" + (string)iPosition.ticket + ") successfully ...";
|
|
// LogMessage(msg);
|
|
// }
|
|
|
|
//
|
|
// LogMessage("OnPositionsChangedHandler ...");
|
|
}
|
|
|
|
//
|
|
// Handle Trade State Changed ...
|
|
void OnTradeStateChangedHandler(
|
|
const XOnTradeHandlerState &state)
|
|
{
|
|
// //
|
|
// string msg = "Trade State Changed ...";
|
|
// LogMessage(msg);
|
|
}
|
|
|
|
//
|
|
// END Event Handlers ...
|
|
//
|
|
|
|
//
|
|
// START Functions ...
|
|
//
|
|
|
|
//
|
|
// Validate Input Args for Initialization ...
|
|
bool ValidateInputs()
|
|
{
|
|
//
|
|
bool result = true;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result =
|
|
//
|
|
xEASlippage > 0 &&
|
|
xEAMagicNumber > 0
|
|
//
|
|
// TODO: add new validations here ...
|
|
//
|
|
;
|
|
|
|
//
|
|
// Logging State ...
|
|
string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ...";
|
|
LogMessage(message);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Signal Provider Struct from User Input ...
|
|
bool InitializeProviders()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Account Manager ...
|
|
xEAAccount = new XSCAccount();
|
|
|
|
//
|
|
// Trader ...
|
|
xEATrade = new XSCTrade(
|
|
xEASlippage,
|
|
xEAMagicNumber);
|
|
|
|
//
|
|
// Attach Event Handlers ...
|
|
xEATrade.AddOnStopLossEventHandler(OnStopLossTriggered);
|
|
xEATrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
|
|
xEATrade.AddOnDealsChangedEventHandler(OnDealsChangedHandler);
|
|
xEATrade.AddOnOrdersChangedEventHandler(OnOrdersChangedHandler);
|
|
xEATrade.AddOnPositionsChangedEventHandler(OnPositionsChangedHandler);
|
|
xEATrade.AddOnTradeStateChangedEventHandler(OnTradeStateChangedHandler);
|
|
|
|
//
|
|
// Prepare Config ...
|
|
//
|
|
// Prepare Default and Clean Config ...
|
|
// in this Config non of Indicators doesn't Draw anything on chart ...
|
|
// TODO: We Have to Get These from Inputs of Users ...
|
|
X121ProviderInputs configs;
|
|
|
|
//
|
|
// XCT ...
|
|
// Candle Timing ...
|
|
configs.xctConfig.clr = clrBlueViolet;
|
|
configs.xctConfig.corner = CORNER_RIGHT_UPPER;
|
|
configs.xctConfig.showCandleTime = true;
|
|
|
|
//
|
|
// XCC ...
|
|
// Candle Styling ...
|
|
configs.xccConfig.upColor = clrLime;
|
|
configs.xccConfig.downColor = clrRed;
|
|
configs.xccConfig.lineColor = clrLime;
|
|
configs.xccConfig.bearishColor = clrRed;
|
|
configs.xccConfig.bullishColor = clrLime;
|
|
configs.xccConfig.volumesColor = clrGreen;
|
|
configs.xccConfig.showCandles = true;
|
|
|
|
//
|
|
// XHK ...
|
|
// HikenAshi Candle Representing ...
|
|
configs.xhkConfig.drawCandleLines = false;
|
|
|
|
//
|
|
// XTM ...
|
|
// Trend Magic ...
|
|
configs.xtmConfig.length = 35;
|
|
configs.xtmConfig.shift = 0;
|
|
configs.xtmConfig.method = MODE_SMA;
|
|
configs.xtmConfig.appliedTo = PRICE_LOW;
|
|
configs.xtmConfig.showLine = false;
|
|
|
|
//
|
|
// XPV ...
|
|
// Peaks And Vales ...
|
|
configs.xpvConfig.shortLength = 9;
|
|
configs.xpvConfig.mediumLength = 17;
|
|
configs.xpvConfig.longLength = 26;
|
|
configs.xpvConfig.hindLength = 35;
|
|
configs.xpvConfig.fiboLevel1 = 0.382;
|
|
configs.xpvConfig.fiboLevel2 = 0.5;
|
|
configs.xpvConfig.fiboLevel3 = 0.618;
|
|
configs.xpvConfig.hhMode = MODE_HIGH;
|
|
configs.xpvConfig.llMode = MODE_LOW;
|
|
configs.xpvConfig.showPeaksAndVales = false;
|
|
configs.xpvConfig.showLevels = false;
|
|
configs.xpvConfig.showFibo1Levels = false;
|
|
configs.xpvConfig.showFibo2Levels = false;
|
|
configs.xpvConfig.showFibo3Levels = false;
|
|
|
|
//
|
|
// XAMA ...
|
|
// Adaptive Moving Average ...
|
|
configs.xamaConfig.length = 52;
|
|
configs.xamaConfig.fastEMA = 2;
|
|
configs.xamaConfig.slowEMA = 30;
|
|
configs.xamaConfig.maShift = 0;
|
|
configs.xamaConfig.appliedTo = PRICE_LOW;
|
|
configs.xamaConfig.showLine = false;
|
|
|
|
//
|
|
// XMRB ...
|
|
// Moving Average Ribbon ...
|
|
configs.xmrbConfig.fast1Length = 3;
|
|
configs.xmrbConfig.slow1Length = 5;
|
|
configs.xmrbConfig.fast2Length = 8;
|
|
configs.xmrbConfig.slow2Length = 13;
|
|
configs.xmrbConfig.fast3Length = 21;
|
|
configs.xmrbConfig.slow3Length = 34;
|
|
configs.xmrbConfig.fast4Length = 55;
|
|
configs.xmrbConfig.slow4Length = 89;
|
|
configs.xmrbConfig.fast5Length = 144;
|
|
configs.xmrbConfig.slow5Length = 233;
|
|
configs.xmrbConfig.ribbonMode = MODE_EMA;
|
|
configs.xmrbConfig.ribbonAppliedTo = PRICE_CLOSE;
|
|
configs.xmrbConfig.showFastMa = false;
|
|
configs.xmrbConfig.showSlowMa = false;
|
|
configs.xmrbConfig.showRibbon = false;
|
|
|
|
//
|
|
// XCHE ...
|
|
// Chandelier Exit Points ...
|
|
configs.xcheConfig.length = 35;
|
|
configs.xcheConfig.loopback = 26;
|
|
configs.xcheConfig.multiplier1 = 3;
|
|
configs.xcheConfig.multiplier2 = 3.5;
|
|
configs.xcheConfig.upAppliedTo = PRICE_HIGH;
|
|
configs.xcheConfig.downAppliedTo = PRICE_LOW;
|
|
configs.xcheConfig.showLongExit1Line = false;
|
|
configs.xcheConfig.showShortExit1Line = false;
|
|
configs.xcheConfig.showLongExit2Line = false;
|
|
configs.xcheConfig.showShortExit2Line = false;
|
|
|
|
//
|
|
// XICH ...
|
|
// Ichimopku Kinko Hyo ...
|
|
configs.xichConfig.tenkanSenLength = 9;
|
|
configs.xichConfig.tenkanSenMode = X_XICH_HH_LL_MODE;
|
|
configs.xichConfig.kijunSenLength = 26;
|
|
configs.xichConfig.kijunSenMode = X_XICH_HH_LL_MODE;
|
|
configs.xichConfig.senkouSpanBLength = 52;
|
|
configs.xichConfig.senkouSpanBMode = X_XICH_HH_LL_MODE;
|
|
configs.xichConfig.chikuoSpanAppliedTo = PRICE_CLOSE;
|
|
configs.xichConfig.showTenkanSen = false;
|
|
configs.xichConfig.showKijunSen = false;
|
|
configs.xichConfig.showKijunSenPlus = false;
|
|
configs.xichConfig.showKijunSenNegative = false;
|
|
configs.xichConfig.showChikouSpan = false;
|
|
configs.xichConfig.showSenkouSpanA = false;
|
|
configs.xichConfig.showSenkouSpanB = false;
|
|
configs.xichConfig.showKumo = false;
|
|
configs.xichConfig.shiftKumo = true;
|
|
|
|
//
|
|
// XTRND ...
|
|
// Trend Detector ...
|
|
configs.xtrndConfig.cycleLength = 2;
|
|
configs.xtrndConfig.numberOfVerifications = 2;
|
|
configs.xtrndConfig.hhMode = MODE_HIGH;
|
|
configs.xtrndConfig.llMode = MODE_LOW;
|
|
configs.xtrndConfig.l1Method = X_PERIOD_AUTO;
|
|
configs.xtrndConfig.l1Period = NULL;
|
|
configs.xtrndConfig.l2Method = X_PERIOD_AUTO;
|
|
configs.xtrndConfig.l2Period = NULL;
|
|
configs.xtrndConfig.l3Method = X_PERIOD_AUTO;
|
|
configs.xtrndConfig.l3Period = NULL;
|
|
configs.xtrndConfig.showConsolidations = false;
|
|
configs.xtrndConfig.showTrend = false;
|
|
configs.xtrndConfig.showL1Trend = false;
|
|
configs.xtrndConfig.showL2Trend = false;
|
|
configs.xtrndConfig.showL3Trend = false;
|
|
|
|
//
|
|
// XSSLC ...
|
|
// SSL Channel ...
|
|
configs.xsslcConfig.length = 36;
|
|
configs.xsslcConfig.method = MODE_SMA;
|
|
configs.xsslcConfig.upAppliedTo = PRICE_HIGH;
|
|
configs.xsslcConfig.downAppliedTo = PRICE_LOW;
|
|
configs.xsslcConfig.showUp = false;
|
|
configs.xsslcConfig.showDown = false;
|
|
|
|
//
|
|
// XHULL ...
|
|
// Hull Trend Detection Channel ...
|
|
configs.xhullConfig.length = 72;
|
|
configs.xhullConfig.divisor = 2;
|
|
configs.xhullConfig.upAppliedTo = PRICE_HIGH;
|
|
configs.xhullConfig.downAppliedTo = PRICE_LOW;
|
|
configs.xhullConfig.showUpZone = false;
|
|
configs.xhullConfig.showDownZone = false;
|
|
|
|
//
|
|
// Default Configs For Different States ...
|
|
bool showPV = true;
|
|
bool showHK = true;
|
|
bool showCHE = true;
|
|
bool showTRND = true;
|
|
bool simpleIchi = true;
|
|
|
|
//
|
|
|
|
//
|
|
if (showHK)
|
|
{
|
|
//
|
|
// Hiken Ashi ...
|
|
configs.xccConfig.showCandles = false;
|
|
configs.xhkConfig.drawCandles = true;
|
|
}
|
|
if (showPV)
|
|
{
|
|
//
|
|
// Peaks and Vales ...
|
|
configs.xpvConfig.showFibo1Levels = true;
|
|
configs.xpvConfig.showFibo2Levels = true;
|
|
configs.xpvConfig.showFibo3Levels = true;
|
|
configs.xpvConfig.showPeaksAndVales = true;
|
|
}
|
|
if (simpleIchi)
|
|
{
|
|
//
|
|
// Simple Ichimoku Kinko Hyo ...
|
|
configs.xichConfig.showKijunSen = true;
|
|
configs.xichConfig.showTenkanSen = true;
|
|
configs.xichConfig.showSenkouSpanA = true;
|
|
configs.xichConfig.showSenkouSpanB = true;
|
|
}
|
|
if (showCHE)
|
|
{
|
|
//
|
|
// Chandelier Exit ...
|
|
configs.xcheConfig.showLongExit1Line = true;
|
|
configs.xcheConfig.showLongExit2Line = true;
|
|
configs.xcheConfig.showShortExit1Line = true;
|
|
configs.xcheConfig.showShortExit2Line = true;
|
|
}
|
|
if (showTRND)
|
|
{
|
|
//
|
|
// Show Trend ...
|
|
configs.xtrndConfig.showL1Trend = true;
|
|
configs.xtrndConfig.showL2Trend = true;
|
|
configs.xtrndConfig.showL3Trend = true;
|
|
}
|
|
|
|
//
|
|
xEAProvider = new XSCX121Provider(
|
|
_Symbol,
|
|
_Period);
|
|
|
|
//
|
|
// Attach Event Handlers ...
|
|
xEAProvider.AddOnSignalConditionEventHandler(OnSignalConditionsRecieved);
|
|
|
|
//
|
|
// Initialize Provider ...
|
|
result = xEAProvider.SetConfig(configs);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void CallProvidersOnTick()
|
|
{
|
|
//
|
|
// int providersCount = ArraySize(xEAProviders);
|
|
// if (providersCount <= 0)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// //
|
|
// // Loop Through Providers ...
|
|
// for (int i = 0; i < providersCount; i++)
|
|
// {
|
|
// //
|
|
// X121SignalProvider providerDescriptor = xEAProviders[i];
|
|
|
|
// //
|
|
// providerDescriptor.provider.OnTick();
|
|
// }
|
|
|
|
//
|
|
xEAProvider.OnTick();
|
|
}
|
|
|
|
//
|
|
void GetPositions(
|
|
XPosition &result[], // Hold Result ...
|
|
string symbol = NULL, // Trading Symbol ...
|
|
ENUM_POSITION_TYPE type = NULL, // Trading Type ...
|
|
ENUM_TIMEFRAMES period = NULL, // Trading Period ...
|
|
ENUM_X121_SIGNAL_PROVIDERS provider = NULL // Trade Provider ...
|
|
)
|
|
{
|
|
//
|
|
Clean(result);
|
|
|
|
//
|
|
int positionsCount = xEATrade.PositionsCount();
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XPosition positions[];
|
|
xEATrade.GetPositions(
|
|
positions,
|
|
symbol,
|
|
period);
|
|
positionsCount = ArraySize(positions);
|
|
if (positionsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (provider == NULL && type == NULL)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
result,
|
|
ArraySize(positions));
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
Add(
|
|
positions[i],
|
|
result);
|
|
}
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[i];
|
|
|
|
//
|
|
ENUM_X121_SIGNAL_PROVIDERS iProvider = ExtractProvider(iPosition);
|
|
if (provider != NULL && iProvider != provider)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (type == NULL || iPosition.type == type)
|
|
{
|
|
//
|
|
Add(
|
|
iPosition,
|
|
result);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// START Guard Functions ...
|
|
//
|
|
|
|
//
|
|
// Do Guard Actions ...
|
|
void HandleGuard()
|
|
{
|
|
//
|
|
// Retrieve Provider Guard Actions ...
|
|
X121Guard guards[];
|
|
xEAProvider.ProvideGuard(guards);
|
|
int guardsCount = ArraySize(guards);
|
|
if (guardsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < guardsCount; i++)
|
|
{
|
|
//
|
|
X121Guard iGuard = guards[i];
|
|
|
|
//
|
|
switch (iGuard.action)
|
|
{
|
|
//
|
|
// Hedge In Profit Specified Positions ...
|
|
case X_GUARD_ACTION_HEDGE:
|
|
HandleGuardHedgeAction(
|
|
iGuard.provider,
|
|
iGuard.symbol,
|
|
iGuard.type,
|
|
iGuard.period);
|
|
break;
|
|
|
|
//
|
|
// Trail Stop Loss in Specified Positions ...
|
|
case X_GUARD_ACTION_TRAIL_STOP:
|
|
HandleGuardTrailingStopAction(
|
|
iGuard.provider,
|
|
iGuard.symbol,
|
|
iGuard.type,
|
|
iGuard.period,
|
|
iGuard.dblPayLoad);
|
|
break;
|
|
|
|
//
|
|
// Force Close Specified Positions ...
|
|
case X_GUARD_ACTION_FORCE_CLOSE:
|
|
HandleGuardForceCloseAction(
|
|
iGuard.provider,
|
|
iGuard.symbol,
|
|
iGuard.type,
|
|
iGuard.period);
|
|
break;
|
|
|
|
//
|
|
// Generate and Place Support Signals ...
|
|
case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL:
|
|
HandleGuardAddSupportPositionAction(
|
|
iGuard.provider,
|
|
iGuard.symbol,
|
|
iGuard.type,
|
|
iGuard.period);
|
|
break;
|
|
|
|
//
|
|
// Delete All Placed Pending Orders ...
|
|
case X_GUARD_ACTION_CANCEL_PENDING_ORDERS:
|
|
HandleGuardCancelPendingOrdersAction(
|
|
iGuard.provider,
|
|
iGuard.symbol,
|
|
iGuard.type,
|
|
iGuard.period);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All Specified Provider's Positions in Profit Summary ...
|
|
void HandleGuardHedgeAction(
|
|
string provider, // Positions Provided by Specific Provider
|
|
string symbol, // Trading Symbol
|
|
ENUM_POSITION_TYPE type, // Trading Type
|
|
ENUM_TIMEFRAMES period // Specified Time Frame
|
|
)
|
|
{
|
|
//
|
|
// TODO: Implement this ...
|
|
}
|
|
|
|
//
|
|
// Force Close Specified Set Of Position ...
|
|
void HandleGuardForceCloseAction(
|
|
string provider, // Positions Provided by Specific Provider
|
|
string symbol, // Trading Symbol
|
|
ENUM_POSITION_TYPE type, // Trading Type
|
|
ENUM_TIMEFRAMES period // Specified Time Frame
|
|
)
|
|
{
|
|
//
|
|
ENUM_X121_SIGNAL_PROVIDERS mProvider = ExtractProvider(provider);
|
|
|
|
//
|
|
XPosition positions[];
|
|
GetPositions(
|
|
positions,
|
|
symbol,
|
|
type,
|
|
period,
|
|
mProvider);
|
|
if (ArraySize(positions) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
string comment = provider + " Force Close Due Market Sense Change ...";
|
|
xEATrade.ClosePositions(
|
|
positions,
|
|
comment);
|
|
|
|
//
|
|
LogMessage(comment);
|
|
}
|
|
|
|
//
|
|
// Trailing Specified Set Of Positions Stop Losses ...
|
|
void HandleGuardTrailingStopAction(
|
|
string provider, // Positions Provided by Specific Provider
|
|
string symbol, // Trading Symbol
|
|
ENUM_POSITION_TYPE type, // Trading Type
|
|
ENUM_TIMEFRAMES period, // Specified Time Frame
|
|
double sl // Desired SL Value ...
|
|
)
|
|
{
|
|
//
|
|
// TODO: Implement this ...
|
|
}
|
|
|
|
//
|
|
// Add Support Signal for Specified Positions ...
|
|
void HandleGuardAddSupportPositionAction(
|
|
string provider, // Positions Provided by Specific Provider
|
|
string symbol, // Trading Symbol
|
|
ENUM_POSITION_TYPE type, // Trading Type
|
|
ENUM_TIMEFRAMES period // Specified Time Frame
|
|
)
|
|
{
|
|
//
|
|
// TODO: Implement this ...
|
|
}
|
|
|
|
//
|
|
// Cancel all Placed Orders ...
|
|
void HandleGuardCancelPendingOrdersAction(
|
|
string provider, // Positions Provided by Specific Provider
|
|
string symbol, // Trading Symbol
|
|
ENUM_POSITION_TYPE type, // Trading Type
|
|
ENUM_TIMEFRAMES period // Specified Time Frame
|
|
)
|
|
{
|
|
//
|
|
// TODO: Implement this ...
|
|
}
|
|
|
|
//
|
|
// END Guard Functions ...
|
|
//
|
|
|
|
//
|
|
// END Functions ...
|
|
//
|