- Expert Class; - Class Based EA; - Signaller(s); - Multi Symbol; - Multi Session; - ...
1154 lines
31 KiB
Plaintext
1154 lines
31 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center XCATB MQL5 Expert Advisor
|
|
// -------------------------------------------------
|
|
// Name: XCAEA
|
|
// Description: an Exper Advisor which used XCATB
|
|
//
|
|
// 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 "EA based on X121 XCATB indicator"
|
|
#property strict
|
|
|
|
//
|
|
// Include Common Library ...
|
|
#include "../Classes/x-saherelm.x-guard.class.mq5"
|
|
#include "../Classes/x-saherelm.x-volume.class.mq5"
|
|
#include "../XCATBEA/Classes/xcatbea.signaller.class.mq5"
|
|
#include "../XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5"
|
|
|
|
//
|
|
#define ShortName "XCATBEA"
|
|
|
|
//
|
|
// Inputs ...
|
|
|
|
//
|
|
// Common ...
|
|
input group "Common";
|
|
input long eaMagicNumber = 1694056; // Magic Number
|
|
input int eaSlippage = 10; // Slippgae
|
|
input string eaLogSuffix = ""; // Log Suffix
|
|
|
|
//
|
|
// Detector ...
|
|
input group "Detector";
|
|
|
|
//
|
|
// Validating ...
|
|
input group "Validations";
|
|
input bool eaForceHasSwing = false; // Force Block to Has Propper Swing
|
|
input bool eaForceOBBarType = false; // Force Order Block to Has InDirectional Bars
|
|
input int eaMinRequiredOBBar = 0; // Min Required OB Bar
|
|
input bool eaForceFVGBarType = false; // Force Fair Value Gaps Bars Type
|
|
input int eaLiquidityLoopback = 0; // Liquidity Detection Loopback
|
|
input double eaMaxAllowedRange = 0.0; // Max Allowed Order Block Range
|
|
input double eaMinAllowedRange = 0.0; // Min Allowed Order Block Range
|
|
input bool eaForceHasFLiquidity = false; // Force Order Block To Has Reversal Liquidity
|
|
input bool eaForceHasRLiquidity = false; // Force Order Block to Has Following Liquidity
|
|
input bool eaValidateGapSequence = false; // Validate Fair Value Gaps Bar Sequences
|
|
input int eaMinAllowedBlockLength = 0; // Min Allowed Block Length
|
|
input bool eaValidateBlockEdgeBreakout = false; // Validate Order Block Edge Breakeout
|
|
|
|
//
|
|
// Filtering ...
|
|
input group "Filters";
|
|
input bool eaFilterBasedOnKI = false; // Filter Based On KI Flats
|
|
input bool eaFilterBasedOnPV = false; // Filter Based On PV
|
|
input int eaBosLoopback = 0; // PV Based Filtering BOS Lookup
|
|
input bool eaFilterBasedOnSar = false; // Filter Based On SAR
|
|
input bool eaForceSarSwitched = false; // SAR Switched on Sides for Filtering
|
|
input bool eaForceSarOnBothSide = false; // SAR Check on Both Sides for Filtering
|
|
input bool eaForceSarHasBreakout = false; // SAR Must Breakout
|
|
input bool eaForceSarHasReversalSide = false; // SAR Must Has Reversal Direction
|
|
input bool eaFilterBasedOnRSI = false; // Filter Based On RSI
|
|
input bool eaForceHasRSITrending = false; // RSI Must Has Trending
|
|
input bool eaForceHasRSIVPattern = false; // RSI Must Has Pattern
|
|
input bool eaForceHasRSICrossing = false; // RSI Must Has Crossing Levels
|
|
input bool eaFilterBasedOnADX = false; // Filter Based On ADX
|
|
input bool eaForceHasADXTrending = false; // ADX Must Has Trending
|
|
input bool eaForceHasADXCrossing = false; // ADX Must Has Crossing +DI/-DI
|
|
input bool eaFilterBasedOnATR = false; // Filter Based On ATR
|
|
input bool eaForceHasATRTrending = false; // ATR Must Has Trending
|
|
input bool eaForceHasATRBreakout = false; // ATR Must Has Breakout
|
|
input bool eaFilterBasedOnTrend = false; // Filter Based On Trend
|
|
input bool eaForceHasTrendDir = false; // TREND Must Has Following Direction
|
|
input bool eaForceHasTrendPlace = false; // TREND Place Based Filtering
|
|
input bool eaForceHasTrendChange = false; // TREND Change Filtering
|
|
input bool eaForceHasTrendTrending = false; // TREND Must Has Trending
|
|
input bool eaForceHasTrendRejection = false; // TREND Line Must Rejected
|
|
input bool eaForceHasTrendLineInside = false; // TREND Line has Inside
|
|
input bool eaForceHasTrendDirOnBothSide = false; // TREND Must Has Following Direction in Both Side
|
|
input bool eaFilterBasedOnDelta = false; // Filter Based On Delta
|
|
input bool eaFilterBasedOnVolume = false; // Filter Based On Volume
|
|
input bool eaFilterBasedOnSignalBar = false; // Filter Based on Signal Bar
|
|
input bool eaFilterBasedOnRoundPrice = false; // Filter Based On Round Prices
|
|
input bool eaFilterBasedOnHKSignalBar = false; // Filter Based On HK Signal Bar
|
|
|
|
//
|
|
// Signal ...
|
|
input group "Signal";
|
|
input int eaSignalR2R = 2; // Risk Reward Ratio
|
|
input double eaSLATRMultiplier = 0; // ATR Multiplier for SL
|
|
|
|
//
|
|
// Volume ...
|
|
input group "Volume";
|
|
input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // Volume Applying Type
|
|
input double eaStaticVoluem = 0.0; // Static Volume
|
|
input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume
|
|
input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing
|
|
input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade
|
|
input double eaConstantPercent = 0.5; // Constant Percent of Balance Per Trade
|
|
input double eaConstantBalance = 0.0; // Constant Balance for Calculations
|
|
|
|
//
|
|
// Management ...
|
|
// eaSessions => (SYDNEY_02:00_14:00),(NY_19:00_23:00)
|
|
input group "Management";
|
|
input bool eaAllowGuards = false; // Allow Guards
|
|
input bool eaAllowTrade = true; // Allow Trade on Signals
|
|
input bool eaAllowLongs = true; // Allow Long Trades
|
|
input bool eaAllowShorts = true; // Allow Short Trades
|
|
input string eaSessions = ""; // Active Sessions
|
|
input ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; // Restrictions Period
|
|
input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period
|
|
input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period
|
|
input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period
|
|
input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades
|
|
input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade
|
|
input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade
|
|
input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time
|
|
|
|
//
|
|
// Alert ...
|
|
// Here we Provider All Requirements for
|
|
// Configuring Alert Provider ...
|
|
input group "Alert";
|
|
input bool eaEnableAlerts = true; // Enable Alerts
|
|
input bool eaLogAlerts = true; // Log Alerts
|
|
input bool eaMailAlerts = false; // Mail Alerts
|
|
input bool eaPushAlerts = true; // Push Alerts
|
|
input bool eaTerminalAlerts = false; // Terminal Alerts
|
|
|
|
//
|
|
// Time Report ...
|
|
input group "Reports";
|
|
input bool eaReportNewMonths = false; // Report New Month
|
|
input bool eaReportNewWeeks = false; // Report New Weeks
|
|
input bool eaReportNewDays = true; // Report New Days
|
|
input bool eaReportNewHours = false; // Report New Hours
|
|
input bool eaReportTrades = true; // Report Trades
|
|
input bool eaReportSignals = true; // Report Signals
|
|
input bool eaReportProtector = true; // Report Protector Actions
|
|
input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished
|
|
|
|
//
|
|
// Collector ...
|
|
input group "Collector";
|
|
input bool eaSaveTrades = false; // Save Trades
|
|
input bool eaSaveSignals = false; // Save Signals
|
|
input bool eaSaveWins = false; // Save Winning Conditions
|
|
input bool eaSaveLosts = false; // Save Lost Conditions
|
|
|
|
//
|
|
// Variables ...
|
|
|
|
//
|
|
XCAlert *eaAlert; // EA Scope Alert Handler ...
|
|
XCTrade *eaTrade; // EA Scope Trade Handler ...
|
|
XCGuard *eaGuard; // EA Scope Guard Handler ...
|
|
string eaTag = ""; // Specified Alert Tag for EA ...
|
|
XCVolume *eaVolume; // EA Scope Voluem Handler ...
|
|
XTimeTracker eaTimeTracker; // EA Scope Time Tracker ...
|
|
XCXCATBEASignaller *eaSignallers[]; // EA Signallers Collection ...
|
|
XCXCATBEATradeManager *eaTradeManager; // EA Scope Trade Manager ...
|
|
|
|
//
|
|
// Event Handlers ...
|
|
|
|
//
|
|
// Initialization ...
|
|
int OnInit()
|
|
{
|
|
//
|
|
// Validate Inputs and Required Parameters
|
|
// for EA to Works fine ...
|
|
if (!ValidateInputs())
|
|
{
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
// Initial Requirements ...
|
|
InitRequirements();
|
|
|
|
//
|
|
// Initialize Volume Manger ...
|
|
if (!InitVolume())
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
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
|
|
|
|
//
|
|
delete eaAlert;
|
|
ZeroMemory(eaAlert);
|
|
|
|
//
|
|
delete eaTrade;
|
|
ZeroMemory(eaTrade);
|
|
|
|
//
|
|
delete eaGuard;
|
|
ZeroMemory(eaGuard);
|
|
|
|
//
|
|
delete eaVolume;
|
|
ZeroMemory(eaVolume);
|
|
|
|
//
|
|
eaTimeTracker.Clean();
|
|
|
|
//
|
|
Clean(eaSignallers);
|
|
|
|
//
|
|
delete eaTradeManager;
|
|
ZeroMemory(eaTradeManager);
|
|
|
|
//
|
|
DestroyTimer();
|
|
}
|
|
|
|
//
|
|
// On Tick Handler ...
|
|
void OnTick()
|
|
{
|
|
//
|
|
// Time Report Handling ...
|
|
HandleTimeReport();
|
|
|
|
//
|
|
// Position Management / Protections Handling ...
|
|
eaTradeManager.Manage();
|
|
|
|
//
|
|
// Count Signallers ...
|
|
bool has = HasChild(eaSignallers);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XGuard guards[];
|
|
XCATBEAStrategyConditions conditions[];
|
|
|
|
//
|
|
int count = ArraySize(eaSignallers);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Retrieve indexed Signaller ...
|
|
XCXCATBEASignaller *iSignaller = eaSignallers[i];
|
|
|
|
//
|
|
string iSymbol = iSignaller.GetSymbol();
|
|
string iProvider = iSignaller.GetProvider();
|
|
ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod();
|
|
|
|
//
|
|
// Now we Have to Check Handle Tick Resoult ...
|
|
|
|
//
|
|
// Requirements ...
|
|
XGuard iGuards[]; // Hold Provided Guards ...
|
|
XPosition iPositions[]; // Retrieve Signaller Positions ...
|
|
XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ...
|
|
|
|
//
|
|
// Reading Signaller Positions ...
|
|
eaTradeManager.GetPositions(
|
|
iPositions,
|
|
iSymbol,
|
|
iProvider,
|
|
iPeriod //
|
|
);
|
|
|
|
//
|
|
// Processing Tick for Signaller ...
|
|
iSignaller.ProcessTick(
|
|
iPositions,
|
|
iGuards,
|
|
iConditions //
|
|
);
|
|
|
|
//
|
|
// Check Results ...
|
|
has = HasChild(iGuards);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
iGuards,
|
|
guards,
|
|
false // Force Clean ...
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check Triggered Conditions ...
|
|
has = iConditions.IsValid() &&
|
|
iConditions.IsSetuped() &&
|
|
iConditions.CanTrigger();
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iConditions,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
Clean(iGuards);
|
|
Clean(iPositions);
|
|
iConditions.Clean();
|
|
}
|
|
|
|
//
|
|
// Do Actions Based on Provided Info ...
|
|
|
|
//
|
|
// Guards ...
|
|
has = HasChild(guards);
|
|
if (has)
|
|
{
|
|
//
|
|
// Handle Guards Firing ...
|
|
eaGuard.DoGuards(guards);
|
|
}
|
|
|
|
//
|
|
// Triggers ...
|
|
has = HasChild(conditions);
|
|
if (has)
|
|
{
|
|
//
|
|
// Handle Conditions Triggering ...
|
|
TriggerConditions(conditions);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
Clean(guards);
|
|
Clean(conditions);
|
|
}
|
|
|
|
//
|
|
// Handle On Trade Event ...
|
|
void OnTrade()
|
|
{
|
|
eaTrade.HandleOnTrade();
|
|
}
|
|
|
|
//
|
|
// On Timer ...
|
|
void OnTimer()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Chart Event Handler ...
|
|
void OnChartEvent(
|
|
const int id,
|
|
const long &lparam,
|
|
const double &dparam,
|
|
const string &sparam //
|
|
)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Event Listeners ...
|
|
|
|
/**
|
|
* Handle StopLoss Triggered Positions ...
|
|
*
|
|
* @param deal: XDeal instance ...
|
|
*/
|
|
void OnStopLossTriggered(const XDeal &deal)
|
|
{
|
|
eaTradeManager.HandleSL(deal);
|
|
}
|
|
|
|
/**
|
|
* Handle Take Profit Triggered Positions ...
|
|
*
|
|
* @param deal: XDeal instance ...
|
|
*/
|
|
void OnTakeProfitTriggered(const XDeal &deal)
|
|
{
|
|
eaTradeManager.HandleTP(deal);
|
|
}
|
|
|
|
/**
|
|
* Handle Force Close a Position ...
|
|
*
|
|
* @param ticket: ULONG ...
|
|
* @param position: XPosition instance ...
|
|
* @param comment: string ...
|
|
*/
|
|
void OnPositionForceClosed(
|
|
const ulong ticket,
|
|
const XPosition &position,
|
|
const string comment //
|
|
)
|
|
{
|
|
eaTradeManager.HandleForceClose(position);
|
|
}
|
|
|
|
/**
|
|
* Handle Position Partially Closed Event ...
|
|
*
|
|
* @param ticket: ULONG ...
|
|
* @param profit: double ...
|
|
* @param comment: string ...
|
|
*/
|
|
void OnPositionPartiallyClosed(
|
|
const ulong ticket,
|
|
const double profit,
|
|
const string comment //
|
|
)
|
|
{
|
|
eaTradeManager.HandlePartiallyClosed(
|
|
ticket,
|
|
profit,
|
|
comment //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle Deals Changes ...
|
|
*
|
|
* @param count: Integer, Number of Changes ...
|
|
*/
|
|
void OnDealsChanged(int count)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Handle Orders Changes ...
|
|
*
|
|
* @param count: Integer, Number of Changes ...
|
|
*/
|
|
void OnOrdersChanged(int count)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Handle Positions Changes ...
|
|
*
|
|
* @param count: Integer, Number of Changes ...
|
|
*/
|
|
void OnPositionsChanged(int count)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Custom Functions ...
|
|
|
|
/**
|
|
* Validate all Inputs of Expert Adviser ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidateInputs()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
string errMessage = "";
|
|
|
|
//
|
|
bool isCommonValid = (
|
|
//
|
|
eaSlippage > 0 &&
|
|
eaMagicNumber > 0
|
|
//
|
|
);
|
|
if (!isCommonValid)
|
|
{
|
|
//
|
|
errMessage += "common configurations error;" + "\n";
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Common ...
|
|
isCommonValid &&
|
|
//
|
|
// Otere ...
|
|
true
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
// Since here Logger not Initiallized, we Use Raw Print Command ...
|
|
Print(ShortName + " Errors: \n", errMessage);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Initialize Timer ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool InitTimer()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// TODO: Initialize Timer if necessary ...
|
|
// result = EventSetTimer(1);
|
|
// result = EventSetMillisecondTimer(100);
|
|
result = true;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Destroy Timer ...
|
|
*/
|
|
void DestroyTimer()
|
|
{
|
|
//
|
|
// TODO: Use This ...
|
|
// EventKillTimer();
|
|
}
|
|
|
|
/**
|
|
* Initial Volume Manager Class Based on Given Configuration ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool InitVolume()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
eaVolume = new XCVolume();
|
|
|
|
//
|
|
result = eaVolume.Init(
|
|
eaVolumeSelect,
|
|
eaStaticVoluem,
|
|
eaDynamicVolumeStepBalance,
|
|
eaDynamicVolumeStepVolume,
|
|
eaConstantRiskBalance,
|
|
eaConstantPercent,
|
|
eaConstantBalance //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Initial Requirements of EA ...
|
|
*/
|
|
void InitRequirements()
|
|
{
|
|
//
|
|
// Preparing Tags ...
|
|
eaTag =
|
|
(IsValid(eaLogSuffix)
|
|
? eaLogSuffix + "_"
|
|
: "") +
|
|
ShortName;
|
|
|
|
//
|
|
eaAlert = new XCAlert();
|
|
eaAlert.SetPrefix(eaLogSuffix);
|
|
eaAlert.SetLogAlerts(eaLogAlerts);
|
|
eaAlert.SetMailAlerts(eaMailAlerts);
|
|
eaAlert.SetPushAlerts(eaPushAlerts);
|
|
eaAlert.SetEnableAlerts(eaEnableAlerts);
|
|
eaAlert.SetTerminalAlerts(eaTerminalAlerts);
|
|
|
|
//
|
|
// EA Trade ...
|
|
eaTrade = new XCTrade(
|
|
eaSlippage,
|
|
eaMagicNumber,
|
|
eaMaxAllowedSpread,
|
|
eaMaxAllowedPositions,
|
|
eaMaxAllowedDrawdownFactor //
|
|
);
|
|
|
|
//
|
|
eaTrade.AddOnStopLossEventHandler(OnStopLossTriggered);
|
|
eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
|
|
eaTrade.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
|
|
eaTrade.AddOnPartialClosePositionEventHandler(OnPositionPartiallyClosed);
|
|
|
|
//
|
|
// EA Trae Manager ...
|
|
eaTradeManager = new XCXCATBEATradeManager(
|
|
eaTrade //
|
|
);
|
|
|
|
//
|
|
eaTradeManager.SetAlertPrefix(eaTag);
|
|
eaTradeManager.SetAlertLogAlerts(eaLogAlerts);
|
|
eaTradeManager.SetAlertMailAlerts(eaMailAlerts);
|
|
eaTradeManager.SetAlertPushAlerts(eaPushAlerts);
|
|
eaTradeManager.SetAlertEnableAlerts(eaEnableAlerts);
|
|
eaTradeManager.SetAlertTerminalAlerts(eaTerminalAlerts);
|
|
|
|
//
|
|
eaTradeManager.SaveWins(eaSaveWins);
|
|
eaTradeManager.SaveLosts(eaSaveLosts);
|
|
eaTradeManager.SaveTrades(eaSaveTrades);
|
|
eaTradeManager.SaveSignals(eaSaveSignals);
|
|
|
|
//
|
|
// Setting Trade Reports ...
|
|
eaTradeManager
|
|
.SetTradeReports(
|
|
eaReportTrades,
|
|
eaReportSignals,
|
|
eaReportProtector,
|
|
eaReportAfterTradesBalance //
|
|
);
|
|
|
|
//
|
|
// Setting Trade Permissions ...
|
|
eaTradeManager
|
|
.SetTradePermissions(
|
|
eaAllowTrade,
|
|
eaAllowLongs,
|
|
eaAllowShorts //
|
|
);
|
|
|
|
//
|
|
// Setting Trade Restrictions ...
|
|
eaTradeManager
|
|
.SetTradeRestrictions(
|
|
eaRestrictionsPeriod,
|
|
eaMaxAllowedTPs,
|
|
eaMaxAllowedSLs,
|
|
eaMaxAllowedTrades //
|
|
);
|
|
|
|
//
|
|
// EA Guard Initialization ...
|
|
eaGuard = new XCGuard(
|
|
eaTrade //
|
|
);
|
|
|
|
//
|
|
eaGuard.SetAlertPrefix(eaTag);
|
|
eaGuard.SetAlertLogAlerts(eaLogAlerts);
|
|
eaGuard.SetAlertMailAlerts(eaMailAlerts);
|
|
eaGuard.SetAlertPushAlerts(eaPushAlerts);
|
|
eaGuard.SetAlertEnableAlerts(eaEnableAlerts);
|
|
eaGuard.SetAlertTerminalAlerts(eaTerminalAlerts);
|
|
|
|
//
|
|
// Initializing Sessions ...
|
|
string sessions[];
|
|
int sessionsCount = 0;
|
|
bool hasSession = IsValid(eaSessions);
|
|
if (hasSession)
|
|
{
|
|
//
|
|
// Extract Per Symbol Sessions ...
|
|
sessionsCount = SplitContent(
|
|
sessions,
|
|
eaSessions,
|
|
"," //
|
|
);
|
|
|
|
//
|
|
// Try to Extract Start and End Times Series ...
|
|
hasSession = IsValidSize(sessionsCount);
|
|
if (hasSession)
|
|
{
|
|
//
|
|
// Iterate Sessions ...
|
|
for (int i = 0; i < sessionsCount; i++)
|
|
{
|
|
//
|
|
// Ignore unused Cases and Extracts only Content ...
|
|
string iSessionDescriptorStr = ExtractString(sessions[i]);
|
|
bool isInited = IsValid(iSessionDescriptorStr);
|
|
if (isInited)
|
|
{
|
|
//
|
|
// Extract Session Descriptor Data ...
|
|
string parts[];
|
|
int partsCount = SplitContent(
|
|
parts,
|
|
iSessionDescriptorStr,
|
|
"_" //
|
|
);
|
|
isInited = IsValidSize(partsCount) && partsCount == 3;
|
|
if (isInited)
|
|
{
|
|
//
|
|
string iName = parts[0];
|
|
string iStart = parts[1];
|
|
string iEnd = parts[2];
|
|
isInited = IsValid(iName) &&
|
|
IsValid(iStart) &&
|
|
IsValid(iEnd);
|
|
if (isInited)
|
|
{
|
|
//
|
|
// Set Active Session ...
|
|
eaTradeManager
|
|
.SetTradeSession(
|
|
_Symbol,
|
|
iStart,
|
|
iEnd,
|
|
iName //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initializing Signaller(s) ...
|
|
string symbols[];
|
|
Add(
|
|
_Symbol,
|
|
symbols //
|
|
);
|
|
bool hasSymbols = HasChild(symbols);
|
|
if (hasSymbols)
|
|
{
|
|
//
|
|
// Prepare Signaller Inputs ...
|
|
XCATBEASignallerInputs iSignallerInputs;
|
|
|
|
//
|
|
// Common Configs ...
|
|
|
|
//
|
|
// Provider Name ...
|
|
iSignallerInputs.period = _Period;
|
|
iSignallerInputs.provider = "XTRGB";
|
|
iSignallerInputs.allowGuards = eaAllowGuards;
|
|
iSignallerInputs.riskToRewardRatio = eaSignalR2R;
|
|
iSignallerInputs.allowDraws = IsRunningOnTestMode();
|
|
iSignallerInputs.slATRMultiplier = eaSLATRMultiplier;
|
|
|
|
//
|
|
// CATB Indicator ...
|
|
iSignallerInputs.catbInputs.Default();
|
|
iSignallerInputs.catbInputs.Hide();
|
|
|
|
//
|
|
// Make Available all Requirement Buffers of XCATB indicator ...
|
|
iSignallerInputs.catbInputs.showPV = true;
|
|
iSignallerInputs.catbInputs.showKI = true;
|
|
iSignallerInputs.catbInputs.showATRBand = true;
|
|
iSignallerInputs.catbInputs.showPVGolden = true;
|
|
|
|
//
|
|
// Trigger Block Validations ...
|
|
iSignallerInputs.validations.forceHasSwing = eaForceHasSwing;
|
|
iSignallerInputs.validations.forceOBBarType = eaForceOBBarType;
|
|
iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar;
|
|
iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType;
|
|
iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback;
|
|
iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange;
|
|
iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange;
|
|
iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity;
|
|
iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity;
|
|
iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence;
|
|
iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength;
|
|
iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout;
|
|
|
|
//
|
|
// Trigger Block Filters ...
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV;
|
|
iSignallerInputs.filters.bosLoopback = eaBosLoopback;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar;
|
|
iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched;
|
|
iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide;
|
|
iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout;
|
|
iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI;
|
|
iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending;
|
|
iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern;
|
|
iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX;
|
|
iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending;
|
|
iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR;
|
|
iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending;
|
|
iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend;
|
|
iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir;
|
|
iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace;
|
|
iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange;
|
|
iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending;
|
|
iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection;
|
|
iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside;
|
|
iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide;
|
|
|
|
//
|
|
iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI;
|
|
iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta;
|
|
iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume;
|
|
iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar;
|
|
iSignallerInputs.filters.filterBasedOnRoundPrice = eaFilterBasedOnRoundPrice;
|
|
iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar;
|
|
|
|
//
|
|
|
|
//
|
|
// Loop Through Symbols for Signalling Initializing ...
|
|
int symbolsCount = ArraySize(symbols);
|
|
for (int i = 0; i < symbolsCount; i++)
|
|
{
|
|
//
|
|
string iSymbol = symbols[i];
|
|
|
|
//
|
|
iSignallerInputs.symbol = iSymbol;
|
|
if (iSignallerInputs.IsValid())
|
|
{
|
|
//
|
|
// Initialize Signaller ...
|
|
XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs);
|
|
|
|
//
|
|
// Add it to the Signallers List ...
|
|
Add(
|
|
iSignaller,
|
|
eaSignallers //
|
|
);
|
|
|
|
//
|
|
ZeroMemory(iSignaller);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iSignallerInputs.Clean();
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Handling Time Reporting ...
|
|
*/
|
|
void HandleTimeReport()
|
|
{
|
|
//
|
|
if (eaAlert == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Monthly Report ....
|
|
if (eaReportNewMonths &&
|
|
eaTimeTracker.IsNewMonth())
|
|
{
|
|
//
|
|
string msg = "New Month ...";
|
|
|
|
//
|
|
eaAlert.SendAlert(msg);
|
|
}
|
|
|
|
//
|
|
// Weekly Report ....
|
|
if (eaReportNewWeeks &&
|
|
eaTimeTracker.IsNewWeek())
|
|
{
|
|
//
|
|
string msg = "New Week ...";
|
|
|
|
//
|
|
eaAlert.SendAlert(msg);
|
|
}
|
|
|
|
//
|
|
// Daily Report ....
|
|
if (eaReportNewDays &&
|
|
eaTimeTracker.IsNewDay())
|
|
{
|
|
//
|
|
string msg = "New Day ...";
|
|
|
|
//
|
|
eaAlert.SendAlert(msg);
|
|
}
|
|
|
|
//
|
|
// Hourly Report ....
|
|
if (eaReportNewHours &&
|
|
eaTimeTracker.IsNewHour())
|
|
{
|
|
//
|
|
string msg = "New Hour ...";
|
|
|
|
//
|
|
eaAlert.SendAlert(msg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update Signal Targets ...
|
|
*/
|
|
void UpdateSignalTargets(XSignal &signal)
|
|
{
|
|
//
|
|
bool has = signal.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Clean Signal Targets ...
|
|
Clean(signal.targets);
|
|
|
|
//
|
|
// Calculate Requirements ...
|
|
double r2r = eaSignalR2R > 0
|
|
? eaSignalR2R
|
|
: 1;
|
|
double risk = signal.GetRisk();
|
|
double reward = risk * r2r;
|
|
|
|
//
|
|
double isLong = IsLong(signal.type);
|
|
|
|
//
|
|
// Handling Signal TP ...
|
|
signal.tp =
|
|
isLong
|
|
? signal.entry + reward
|
|
: signal.entry - reward;
|
|
|
|
//
|
|
// Try to Apply Money Management ...
|
|
|
|
//
|
|
// if (r2r <= 1)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
//
|
|
// XTarget iTarget;
|
|
|
|
// //
|
|
// // Partial Close 0.5 of Position on Reward 1 ...
|
|
// reward = risk * 1;
|
|
// iTarget.target =
|
|
// isLong
|
|
// ? signal.entry + reward
|
|
// : signal.entry - reward;
|
|
// iTarget.volumeMultiplier = 0.5;
|
|
|
|
// //
|
|
// AddRef(iTarget, signal.targets);
|
|
// iTarget.Clean();
|
|
|
|
// //
|
|
// if (r2r <= 2)
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
//
|
|
// Making Loop ...
|
|
// for (int i = 2; i < ((int)r2r - 1); i++)
|
|
// {
|
|
// //
|
|
// iTarget.Clean();
|
|
|
|
// //
|
|
// reward = i * risk;
|
|
// iTarget.target =
|
|
// isLong
|
|
// ? signal.entry + reward
|
|
// : signal.entry - reward;
|
|
// iTarget.volumeMultiplier = 1 / (r2r - 2);
|
|
|
|
// //
|
|
// AddRef(iTarget, signal.targets);
|
|
// }
|
|
|
|
//
|
|
// Sort Targets ...
|
|
ENUM_X_DIRECTION sortingDir =
|
|
isLong
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
ApplySortOnTargets(
|
|
sortingDir,
|
|
signal.targets //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Convert a Triggered Conditions to Signal and
|
|
* Execute it ...
|
|
*/
|
|
void TriggerConditions(XCATBEAStrategyConditions &conditions[])
|
|
{
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasChild(conditions);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
count = ArraySize(conditions);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Retrieve Indexed Conditions ...
|
|
XCATBEAStrategyConditions iConditions = conditions[i];
|
|
|
|
//
|
|
// Prepare Signal Based on Conditions ...
|
|
XSignal iSignal;
|
|
|
|
//
|
|
// Check if a Trigger Block Attached and Has Signal ...
|
|
// use it ...
|
|
has =
|
|
iConditions.IsValid() &&
|
|
iConditions.IsSetuped() &&
|
|
iConditions.CanTrigger() &&
|
|
iConditions.triggerBlock.IsValid() &&
|
|
iConditions.triggerBlock.signal.IsValid();
|
|
if (has)
|
|
{
|
|
iSignal = iConditions.triggerBlock.signal;
|
|
}
|
|
|
|
//
|
|
// if we Have any other Signalling senarios we can Handle them here ...
|
|
|
|
//
|
|
// Validate Signal ...
|
|
has = iSignal.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
// Retrieve Signal Type ...
|
|
bool isLong = IsLong(iSignal.type);
|
|
|
|
//
|
|
// Update Signal Entry ...
|
|
iSignal.entry = GetEntry(
|
|
iSignal.symbol,
|
|
iSignal.type //
|
|
);
|
|
|
|
//
|
|
// Update Signal Targets ...
|
|
UpdateSignalTargets(iSignal);
|
|
|
|
//
|
|
// Handle Volume Management ...
|
|
double iVolume = eaVolume.CalculateVolume(iSignal);
|
|
has = iVolume > X_MIN_VOLUME &&
|
|
iVolume != iSignal.volume;
|
|
if (has)
|
|
{
|
|
iSignal.volume = iVolume;
|
|
}
|
|
|
|
//
|
|
// Execute Signal ...
|
|
has = eaTradeManager.Execute(
|
|
iSignal,
|
|
iConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iSignal.Clean();
|
|
iConditions.Clean();
|
|
}
|
|
}
|
|
|
|
// |