Files
MQL5Data/Documents/BKP/x-saherelm.xfima.backtester.ea copy.mq5
T
2025-10-01 05:10:42 +03:30

1899 lines
48 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center XTest MQL5 Expert Advisor
// -------------------------------------------------
// Name: XBackTester
// Description: a Backtest Tools Strategy Tester
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////x
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XBackTester"
#property icon "../Images/SaherElm_Logo_Color.ico"
#property strict
//
#define ShortName "XBackTester"
//
// Imports ...
#include "../Classes/x-saherelm.x-backtester.expert.class.mq5"
#include "../XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5"
//
// Definitions ...
//
// Inputs ...
//
// Common ...
input group "Common";
input long eaMagicNumber = 78692110; // Magic Number
input int eaSlippage = 10; // Slippgae
input string eaLogSuffix = ""; // Log Suffix
//
// 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 = false; // Push Alerts
input bool eaTerminalAlerts = false; // Terminal Alerts
//
// Configurations ...
input group "Configuration";
input bool eaProcessAllTicks = false; // Process All Ticks
input double eaSignallerR2R = 2.0; // Risk To Reward Ratio
input double eaSignallerVolume = 0.01; // Default Volume
input double eaSignallerRiskInPoint = 50; // Default Risk In Point
//
// Indicator Inputs ...
//
input group "Calculation";
//
// Short ...
input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period
input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period
//
// Medium ...
input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period
input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period
//
// Long ...
input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period
input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period
//
// Hind ...
input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period
input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period
//
// PV ...
input ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method
input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method
//
// Others ...
input ENUM_X_FIBO_LEVELS fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level
input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Middle Zone Level
input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // Lower Zone Level
input double sarStep = 0.02; // SAR Step
input double sarMax = 0.2; // SAR Maximum
input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method
input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To
input int maFastLength = 7; // Fast MA Length
input int maSlowLength = 20; // Slow MA Length
input int maBandLength = 7; // MA Band Length
input int zigzagDepth = 12; // ZigZag Depth
input int zigzagDeviation = 5; // ZigZag Deviation
input int zigzagBackStep = 3; // ZigZag Back Step
input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode
input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode
//
input group "Bar Timer";
input int barTimeFontSize = 10; // Font Size
input string barTimeFont = "Arial"; // Font
input color barTimeColor = clrYellow; // Text Color
input ENUM_BASE_CORNER barTimeCorner = CORNER_RIGHT_LOWER; // Text Position
//
// Presentation ...
input group "Presentation";
input bool showPV = true; // Show PV
input bool showHK = true; // Show HK
input bool showSAR = true; // Show Sar
input bool showMAFast = true; // Show MA Fast
input bool showMASlow = true; // Show MA Slow
input bool showMABand = true; // Show MA Band
input bool showBarTime = true; // Show Bar Time
input bool showZigZag = true; // Show ZigZag
input bool showFiboZone = true; // Show Fibo Zone
//
input int startCalculationForLastBars = 1500; // Calculate Last n Bars
//
input int sarArrowCode = 159; // Parabolic Sar Arrow Code
input int peakArrowCode = 159; // Peaks Arrow Code
input int valeArrowCode = 159; // Vales Arrow Code
//
// Define Local Variables ...
//
// Requirements ...
string eaLogTag; // EA Log Prefix ...
XCBackTesterEA *eaExpert; // EA Expert ...
//
// Registered Signallers ...
XCXFIMAStrategy1Signaller *fima1Signaller; // XFIMA1 Signaller ...
//
XFIMAMarketStructure marketStructure; // POI Analysis Result ...
XFIMAPatternDetectorConfig detectorConfig; // POI Detector Config ...
XFIMAMarketStructureDrawerConfig marketStructureDrawerConfig; // POI Drawer Config ...
//
// Drawer and eaDraws ...
CArrayObj eaDraws; // Drawn Objects ...
CArrayObj *marketStructureObjects; // Market Structure Objects ...
//
XBarTracker eaBarTracker; // EA Bar Traker ...
//
// Registered Handlers ...
int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ...
//
bool eaIsNewBar; // Check New Bar ...
//
// Define Indicators Here ...
//
// Event Handlers ...
//
// Initialization ...
int OnInit()
{
//
// Preparing Tags ...
string eaTag =
(IsValid(eaLogSuffix)
? eaLogSuffix + "_"
: "") +
ShortName;
//
// Validate Inputs and Required Parameters
// for EA to Works fine ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Initialize Timer ...
if (!InitTimer())
{
return INIT_FAILED;
}
//
// Configure EA Expert Class ...
eaExpert = new XCBackTesterEA();
//
// Symbol / Period ...
eaExpert.symbol = _Symbol;
eaExpert.period = _Period;
//
// Common ...
eaExpert.eaMagicNumber = eaMagicNumber;
eaExpert.eaSlippage = eaSlippage;
eaExpert.eaLogSuffix = eaTag;
//
// Alert ...
eaExpert.eaEnableAlerts = eaEnableAlerts;
eaExpert.eaLogAlerts = eaLogAlerts;
eaExpert.eaMailAlerts = eaMailAlerts;
eaExpert.eaPushAlerts = eaPushAlerts;
eaExpert.eaTerminalAlerts = eaTerminalAlerts;
//
// Attach Event Handlers ...
eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged);
eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered);
eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged);
eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
eaExpert.AddOnModifyPositionEventHandler(OnPositionModified);
eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged);
eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged);
eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed);
//
// Configure Other Requirements ...
eaExpert.allowedTPSLStep = 10;
eaExpert.minAllowedRiskInPoint = 20;
eaExpert.volume = eaSignallerVolume;
eaExpert.riskToRewardRatio = eaSignallerR2R;
eaExpert.riskInPoint = eaSignallerRiskInPoint;
//
// Try to Initialize eaExpert ...
bool isInited = eaExpert.HandleOnInit();
if (!isInited)
{
//
Print(ShortName, ": Initialization Failed ...");
return INIT_FAILED;
}
//
// Here Instantiate Signaller Class ...
//
// Preparing Indicator Inputs ...
XFIMAInputs fimaInputs;
//
// This is Default Configuration ...
fimaInputs.Default();
fimaInputs.Hide();
//
// Here we Attach Inputs to Indicator ...
fimaInputs.scMethod = scMethod;
fimaInputs.scPeriod = scPeriod;
fimaInputs.mcMethod = mcMethod;
fimaInputs.mcPeriod = mcPeriod;
fimaInputs.lcMethod = lcMethod;
fimaInputs.lcPeriod = lcPeriod;
fimaInputs.hcMethod = hcMethod;
fimaInputs.hcPeriod = hcPeriod;
fimaInputs.upperMode = upperMode;
fimaInputs.lowerMode = lowerMode;
fimaInputs.fiboUpperZoneLevel = fiboUpperZoneLevel;
fimaInputs.fiboMiddleZoneLevel = fiboMiddleZoneLevel;
fimaInputs.fiboLowerZoneLevel = fiboLowerZoneLevel;
fimaInputs.sarStep = sarStep;
fimaInputs.sarMax = sarMax;
fimaInputs.maMethod = maMethod;
fimaInputs.maAppliedTo = maAppliedTo;
fimaInputs.maFastLength = maFastLength;
fimaInputs.maSlowLength = maSlowLength;
fimaInputs.maBandLength = maBandLength;
fimaInputs.zigzagDepth = zigzagDepth;
fimaInputs.zigzagDeviation = zigzagDeviation;
fimaInputs.zigzagBackStep = zigzagBackStep;
fimaInputs.zigzagUppersMode = zigzagUppersMode;
fimaInputs.zigzagLowersMode = zigzagLowersMode;
fimaInputs.showPV = showPV;
fimaInputs.showHK = showHK;
fimaInputs.showSAR = showSAR;
fimaInputs.showMAFast = showMAFast;
fimaInputs.showMASlow = showMASlow;
fimaInputs.showMABand = showMABand;
fimaInputs.showZigZag = showZigZag;
fimaInputs.showFiboZone = showFiboZone;
fimaInputs.startCalculationForLastBars = startCalculationForLastBars;
fimaInputs.sarArrowCode = sarArrowCode;
fimaInputs.peakArrowCode = peakArrowCode;
fimaInputs.valeArrowCode = valeArrowCode;
//
// Instantiate Signaller ...
//
// XFIMA1 Signaller ...
fima1Signaller = new XCXFIMAStrategy1Signaller(
_Symbol,
_Period,
fimaInputs,
eaProcessAllTicks, // Process All Ticks ...
eaSignallerR2R, // Signaller Risk to Reward Ratio ...
eaSignallerRiskInPoint, // Default Risk In Points ...
eaSignallerVolume // Defaul Volume ...
);
fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered);
//
isInited =
fima1Signaller.IsValid();
if (!isInited)
{
//
Print(ShortName, ": Initialization Failed ...");
return INIT_FAILED;
}
//
// Initialize Candle Timer Handler ...
eaCTHandler = iCustom(
_Symbol,
_Period,
"x-saherelm.x121.xct",
//
// Inputs ...
barTimeFontSize, // Font Size ...
barTimeFont, // Font ...
barTimeColor, // Text Color ...
barTimeCorner, // Text Position ...
//
// Presentation ...
"",
showBarTime // Show Candle Time
//
);
isInited = eaCTHandler != INVALID_HANDLE;
if (!isInited)
{
//
Print(ShortName, ": Initialization Failed ...");
return INIT_FAILED;
}
//
// Initialize Bar Tracker ...
isInited = eaBarTracker.Init(
_Symbol,
_Period //
);
if (!isInited)
{
//
Print(ShortName, ": Initialization Failed ...");
return INIT_FAILED;
}
//
// Configure XFIMA POI Detector / Drawer ...
detectorConfig.Default();
detectorConfig.FullDetect();
marketStructureDrawerConfig.FullDraw();
//
Print(ShortName, ": Initialized Successfully ...");
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
//
// Destroy Timer ...
eaExpert.HandleOnDeInit();
//
// De Init Indicator ...
IndicatorRelease(eaCTHandler);
//
eaBarTracker.Clean();
//
delete fima1Signaller;
ZeroMemory(fima1Signaller);
//
delete eaExpert;
ZeroMemory(eaExpert);
}
//
// On Tick Handler ...
void OnTick()
{
//
eaIsNewBar = eaBarTracker.IsNewBar();
bool canProcess = eaProcessAllTicks
? true
: eaIsNewBar;
//
eaExpert.HandleOnTick();
//
if (!canProcess)
{
return;
}
//
// Bar Index ...
int barIndex = 1;
//
fima1Signaller.OnTick(barIndex);
//
// AnalyseMarket(barIndex);
}
//
// Handle On Trade Event ...
void OnTrade()
{
eaExpert.HandleOnTrade();
}
//
// On Timer ...
void OnTimer()
{
eaExpert.HandleOnTimer();
}
//
// Chart Event Handler ...
void OnChartEvent(
const int id,
const long &lparam,
const double &dparam,
const string &sparam //
)
{
eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam);
}
//
// Custom Functions ...
/**
* Validate all Inputs of Expert Adviser ...
*
* @return ( bool )
*/
bool ValidateInputs()
{
//
bool result = false;
//
string errMessage = "";
//
bool isCommonValid = (
//
eaSlippage > 0 &&
eaMagicNumber > 0 &&
//
// Indicator Inputs ...
//
// MA ...
maFastLength >= 2 &&
maSlowLength >= 2 &&
maSlowLength > maFastLength &&
//
// SAR ...
sarMax > 0 &&
sarStep > 0 &&
sarMax > sarStep &&
//
// CYCLES ...
(IsValid(scMethod, scPeriod) &&
IsValid(mcMethod, mcPeriod) &&
IsValid(lcMethod, lcPeriod) &&
IsValid(hcMethod, hcPeriod)) &&
//
// ZIGZAG ...
zigzagDepth > 0 &&
zigzagDeviation > 0 &&
zigzagBackStep > 0 &&
//
// Validate Upper Mode Detection ...
IsXValid(zigzagUppersMode) &&
//
// Validate Lower Mode Detection ...
IsXValid(zigzagLowersMode)
//
);
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();
}
/**
* Trigger OnSignal Event ...
*
* @param signal: XSignal
*/
void OnSignalTriggered(XSignal &signal)
{
//
// Validate Signal ...
if (!signal.IsValid())
{
return;
}
//
// TODO: Fix this ...
// return;
//
// Draw Signal on Chart ...
XCSignalObject *iSignalObj;
bool has = fima1Signaller.poiDrawer.DrawSignal(
signal,
iSignalObj,
7 //
);
//
if (has)
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT result;
eaExpert.eaTrader.ExecuteSignal(
signal,
result //
);
//
Print("Signal Issued: ", signal.GetObjectID());
}
//
// Try to Execute Signal ...
//
// Draw Signal Vertical Line ...
// //
// CChartObjectVLine *iObj = new CChartObjectVLine();
// //
// string iName = signal.GetObjectID();
// color iColor = IsLong(signal.type) ? clrLime : clrRed;
// //
// bool has = iObj.Create(
// fima2Signaller.poiDrawer.ChartIdentification(),
// iName,
// fima2Signaller.poiDrawer.SubWindowIdentification(),
// signal.time //
// );
// if (has)
// {
// //
// iObj.Width(2);
// iObj.Color(iColor);
// //
// // eaDraws.Add(iObj);
// }
// //
// // Alert Issued Signal ...
// string message = signal.GetMessage();
//
// int signalBarIndex = GetBarIndex(
// signal.symbol,
// signal.period,
// signal.time //
// );
// AnalyseMarket(signalBarIndex);
}
//
// Trade Event Handlers ...
/**
* Handle StopLoss Triggered Positions ...
*
* @param deal: XDeal instance ...
*/
void OnStopLossTriggered(const XDeal &deal)
{
eaExpert.HandleOnStopLossTriggered(deal);
}
/**
* Handle Take Profit Triggered Positions ...
*
* @param deal: XDeal instance ...
*/
void OnTakeProfitTriggered(const XDeal &deal)
{
eaExpert.HandleOnTakeProfitTriggered(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 //
)
{
//
eaExpert.HandleOnPositionForceClosed(
ticket,
position,
comment //
);
}
/**
* Handle Deals Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnDealsChanged(int count)
{
eaExpert.HandleOnDealsChanged(count);
}
/**
* Handle Orders Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnOrdersChanged(int count)
{
eaExpert.HandleOnOrdersChanged(count);
}
/**
* Handle Positions Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnPositionsChanged(int count)
{
eaExpert.HandleOnPositionsChanged(count);
}
/**
* Handle Position Modified ...
*
* @param ticket: ulong, Position Ticket ...
* @param profit: double, Position Profit ...
* @param comment: string, Comment ...
*/
void OnPositionModified(
const ulong ticket,
const double profit,
const string comment //
)
{
//
eaExpert.HandleOnPositionModified(
ticket,
profit,
comment //
);
}
/**
* Handle Position Partial Closed ...
*
* @param ticket: ulong, Position Ticket ...
* @param profit: double, Position Profit ...
* @param comment: string, Comment ...
*/
void OnPositionPartialClosed(
const ulong ticket,
const double profit,
const string comment //
)
{
//
eaExpert.HandleOnPositionPartialClosed(
ticket,
profit,
comment //
);
}
/**
* Handle Trade State Changed ...
*
* @param state: XOnTradeHandlerState instance ...
*/
void OnTradeStateChanged(const XOnTradeHandlerState &state)
{
eaExpert.HandleOnTradeStateChanged(state);
}
//
void AnalyseMarket(int barIndex = 0)
{
//
bool has = false;
//
barIndex = NormalizeInt(barIndex, 0);
//
string symbol = fima1Signaller.symbol;
ENUM_TIMEFRAMES period = fima1Signaller.period;
//
// Retrieve Signal Bar ...
XOHCL bar;
has = bar.Init(
symbol,
period,
barIndex //
);
if (!has)
{
//
bar.Clean();
return;
}
//
// TODO: Remove this and add in OnInit() Method ...
//
// Configuring Detector ...
//
detectorConfig.detectOB = true;
detectorConfig.detectFVG = true;
//
detectorConfig.detectSupport = true;
detectorConfig.detectResistance = true;
detectorConfig.detectSwingTrend = true;
//
detectorConfig.detectPinned = true;
detectorConfig.detectMomentum = true;
detectorConfig.detectEngulfed = true;
detectorConfig.detectTrueGaped = true;
//
detectorConfig.detectStarPattern = true;
detectorConfig.detectFlagPattern = true;
detectorConfig.detectRisingPattern = true;
detectorConfig.detectPiercingPattern = true;
detectorConfig.detectSignalKeyBarPattern = true;
//
detectorConfig.analyseFIMAPVPivots = true;
detectorConfig.analyseFIMASARPivots = false;
detectorConfig.analyseFIMAZigZagPivots = true;
//
// Configure Drawer ...
//
marketStructureDrawerConfig.drawOB = false;
marketStructureDrawerConfig.drawFVG = false;
//
marketStructureDrawerConfig.drawPinned = false;
marketStructureDrawerConfig.drawEngulfed = true;
marketStructureDrawerConfig.drawTrueGaped = false;
marketStructureDrawerConfig.drawMomentum = false;
marketStructureDrawerConfig.drawFlagPattern = false;
marketStructureDrawerConfig.drawStarPattern = false;
marketStructureDrawerConfig.drawRisingPattern = false;
marketStructureDrawerConfig.drawPiercingPattern = false;
marketStructureDrawerConfig.drawSignalKeyBarPattern = true;
//
// Recents ...
marketStructureDrawerConfig.drawRecentPatterns = false;
marketStructureDrawerConfig.drawFakeBreakedZone = false;
marketStructureDrawerConfig.drawRecentlyTestedZones = false;
marketStructureDrawerConfig.drawRecentlyBreakedZones = false;
//
// XPV ...
marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true;
marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true;
marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true;
marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true;
//
// XSAR ...
marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false;
marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false;
marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false;
marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false;
//
// XZigZag ...
marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true;
marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true;
marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false;
marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false;
//
// Analyse Market on Signalling Bar ...
fima1Signaller.poiDetector.AnalyseMarket(
bar,
marketStructure,
detectorConfig //
);
//
XFIMASIgballer2First(bar);
// HandleLookupSignal(bar);
//
bar.Clean();
}
//
// Handle Signal Looking Up ...
// Register it as XFIMA Signaller 2 ...
void XFIMASIgballer2First(XOHCL &bar)
{
//
bool has =
bar.IsValid();
if (!has)
{
return;
}
//
XBoxZone iZone;
XSignal iSignal;
string iName = NULL;
XBoxZone supports[];
XBoxZone resistances[];
bool isBullish = false;
int barIndex = bar.Index();
double iPrice = EMPTY_VALUE;
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
// Check Required Pattern Exists ...
bool hasPinnedBar = HasDirection(marketStructure.pinnedDir);
bool hasEngulfedBar = HasDirection(marketStructure.engulfedDir);
bool hasFlagPattern = HasDirection(marketStructure.flagPatternDir);
bool hasStarPattern = HasDirection(marketStructure.starPatternDir);
bool hasRisingPattern = HasDirection(marketStructure.risingPatternDir);
bool hasPiercingPattern = HasDirection(marketStructure.piercingPatternDir);
bool hasSignalKeyBar = HasDirection(marketStructure.signalKeyBarPatternDir);
//
// PV Trend Line ...
string pvTrendName = "XPVTrend";
CChartObjectTrend *pvTrendLine = NULL;
ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE;
//
// ZigZag Trend Line ...
string zgTrendName = "XZGTrend";
CChartObjectTrend *zgTrendLine = NULL;
ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE;
//
// Check PV Analysis ...
bool hasPVAnalysis = marketStructure.pvAnalysis.IsValid();
if (hasPVAnalysis)
{
//
// Support ...
XBoxZone supportBox;
XCBoxObject *iSupportObj;
has = marketStructure.pvAnalysis.HasSupportBox(supportBox);
if (has)
{
//
supportBox.to = bar.time;
AddIfNotExists(
supportBox,
supports //
);
has = fima2Signaller.poiDrawer.DrawBox(
supportBox,
iSupportObj,
true, // Ignore At ...
supportBox.type // Name ...
);
if (has)
{
//
XPOIStyle iStyle;
fima2Signaller.poiDrawer.GetBoxStyle(
iStyle,
supportBox.dir //
);
fima2Signaller.poiDrawer.ApplyBoxStyle(
iSupportObj,
iStyle //
);
iStyle.Clean();
}
}
//
// Resistance ...
XBoxZone resistanceBox;
XCBoxObject *iResistanceObj;
has = marketStructure.pvAnalysis.HasResistanceBox(resistanceBox);
if (has)
{
//
resistanceBox.to = bar.time;
AddIfNotExists(
resistanceBox,
supports //
);
has = fima2Signaller.poiDrawer.DrawBox(
resistanceBox,
iResistanceObj,
true, // Ignore At ...
resistanceBox.type // Name ...
);
if (has)
{
//
XPOIStyle iStyle;
fima2Signaller.poiDrawer.GetBoxStyle(
iStyle,
resistanceBox.dir //
);
fima2Signaller.poiDrawer.ApplyBoxStyle(
iResistanceObj,
iStyle //
);
iStyle.Clean();
}
}
//
// Pivots ...
XPivot pivots[];
int pivotsCount = fima2Signaller.poiDetector.ExtractPVPivots(
pivots,
barIndex,
50 //
);
has = IsValidSize(pivotsCount);
//
// Sort ...
Sort(
pivots,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Remove Newest ...
ArrayRemove(
pivots,
0,
1 //
);
//
// Check Trend ...
if (has)
{
//
XPivot highs[];
int highsCount = ExtractPivots(
highs,
pivots,
X_PIVOT_TYPE_PEAK //
);
Sort(
highs,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
XPivot lows[];
int lowsCount = ExtractPivots(
lows,
pivots,
X_PIVOT_TYPE_VALE //
);
Sort(
lows,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Check Highs and Lows ...
has = IsValidSize(lowsCount) &&
IsValidSize(highsCount) &&
lowsCount >= 2 &&
highsCount >= 2;
if (has)
{
//
// Try to Get Market Strucutre ...
//
bool hasLowerHigh = highs[0].value < highs[1].value;
bool hasLowerLow = lows[0].value < lows[1].value;
//
bool hasHigherHigh = highs[0].value > highs[1].value;
bool hasHigherLow = lows[0].value > lows[1].value;
//
pvTrend =
(hasHigherHigh &&
hasHigherLow)
? X_DIRECTION_BULLISH
: (hasLowerHigh &&
hasLowerLow)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(pvTrend);
if (has)
{
//
// Select Swings for Trend Line ...
XOHCL tmpBar;
int llIDX = -1;
int hhIDX = -1;
datetime toTime = NULL;
datetime fromTime = NULL;
double toPrice = EMPTY_VALUE;
color trendColor = CLR_NONE;
double fromPrice = EMPTY_VALUE;
if (IsSpecifiedBullish(pvTrend))
{
//
llIDX = GetLowest(lows);
hhIDX = GetHighest(lows);
//
trendColor = clrAqua;
//
toTime = lows[hhIDX].time;
toPrice = lows[hhIDX].value;
//
fromTime = lows[llIDX].time;
fromPrice = lows[llIDX].value;
}
else
{
//
llIDX = GetLowest(highs);
hhIDX = GetHighest(highs);
//
trendColor = clrMagenta;
//
toTime = highs[llIDX].time;
toPrice = highs[llIDX].value;
//
fromTime = highs[hhIDX].time;
fromPrice = highs[hhIDX].value;
}
//
// Check Requirements for Trend ...
has =
NotEmptyZero(toPrice) &&
NotEmptyZero(fromPrice) &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime);
if (has)
{
//
has = fima2Signaller.poiDrawer.DrawTrendLine(
fromPrice,
fromTime,
toPrice,
toTime,
pvTrendLine,
pvTrendName,
true // Ray Right ...
);
if (has)
{
pvTrendLine.Color(trendColor);
}
}
//
// Cleanup Resources ...
tmpBar.Clean();
}
//
if (!has)
{
SpecifiedClean(pivots);
}
}
//
// Cleanup Resources ...
SpecifiedClean(lows);
SpecifiedClean(highs);
}
//
// Draw Pivots ...
has = HasChild(pivots);
if (has)
{
//
CArrayObj *drawnPivots = new CArrayObj();
pivotsCount = fima2Signaller.poiDrawer.DrawPivots(
pivots,
drawnPivots //
);
}
//
// Cleanup Resources ...
SpecifiedClean(pivots);
}
//
// Check ZigZag Analysis ...
bool hasZGAnalysis = marketStructure.zigzagAnalysis.IsValid();
if (hasZGAnalysis)
{
//
// Support ...
XBoxZone supportBox;
XCBoxObject *iSupportObj;
has = marketStructure.zigzagAnalysis.HasSupportBox(supportBox);
if (has)
{
//
supportBox.to = bar.time;
AddIfNotExists(
supportBox,
supports //
);
has = fima2Signaller.poiDrawer.DrawBox(
supportBox,
iSupportObj,
true, // Ignore At ...
supportBox.type // Name ...
);
if (has)
{
//
XPOIStyle iStyle;
fima2Signaller.poiDrawer.GetBoxStyle(
iStyle,
supportBox.dir //
);
fima2Signaller.poiDrawer.ApplyBoxStyle(
iSupportObj,
iStyle //
);
iStyle.Clean();
}
}
//
// Resistance ...
XBoxZone resistanceBox;
XCBoxObject *iResistanceObj;
has = marketStructure.zigzagAnalysis.HasResistanceBox(resistanceBox);
if (has)
{
//
resistanceBox.to = bar.time;
AddIfNotExists(
resistanceBox,
supports //
);
has = fima2Signaller.poiDrawer.DrawBox(
resistanceBox,
iResistanceObj,
true, // Ignore At ...
resistanceBox.type // Name ...
);
if (has)
{
//
XPOIStyle iStyle;
fima2Signaller.poiDrawer.GetBoxStyle(
iStyle,
resistanceBox.dir //
);
fima2Signaller.poiDrawer.ApplyBoxStyle(
iResistanceObj,
iStyle //
);
iStyle.Clean();
}
}
//
// Pivots ...
XPivot pivots[];
int pivotsCount = fima2Signaller.poiDetector.ExtractZigZagPivots(
pivots,
barIndex,
10 //
);
has = IsValidSize(pivotsCount);
//
// Sort ...
Sort(
pivots,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Remove Newest ...
ArrayRemove(
pivots,
0,
1 //
);
//
// Check Trend ...
if (has)
{
//
XPivot highs[];
int highsCount = ExtractPivots(
highs,
pivots,
X_PIVOT_TYPE_PEAK //
);
Sort(
highs,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
XPivot lows[];
int lowsCount = ExtractPivots(
lows,
pivots,
X_PIVOT_TYPE_VALE //
);
Sort(
lows,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Check Highs and Lows ...
has = IsValidSize(lowsCount) &&
IsValidSize(highsCount) &&
lowsCount >= 2 &&
highsCount >= 2;
if (has)
{
//
// Try to Get Market Strucutre ...
//
bool hasLowerHigh = highs[0].value < highs[1].value;
bool hasLowerLow = lows[0].value < lows[1].value;
//
bool hasHigherHigh = highs[0].value > highs[1].value;
bool hasHigherLow = lows[0].value > lows[1].value;
//
zgTrend =
(hasHigherHigh &&
hasHigherLow)
? X_DIRECTION_BULLISH
: (hasLowerHigh &&
hasLowerLow)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(zgTrend);
if (has)
{
//
// Select Swings for Trend Line ...
XOHCL tmpBar;
int llIDX = -1;
int hhIDX = -1;
datetime toTime = NULL;
datetime fromTime = NULL;
double toPrice = EMPTY_VALUE;
color trendColor = CLR_NONE;
double fromPrice = EMPTY_VALUE;
if (IsSpecifiedBullish(zgTrend))
{
//
llIDX = GetLowest(lows);
hhIDX = GetHighest(lows);
//
trendColor = clrAqua;
//
toTime = lows[hhIDX].time;
toPrice = lows[hhIDX].value;
//
fromTime = lows[llIDX].time;
fromPrice = lows[llIDX].value;
}
else
{
//
llIDX = GetLowest(highs);
hhIDX = GetHighest(highs);
//
trendColor = clrMagenta;
//
toTime = highs[llIDX].time;
toPrice = highs[llIDX].value;
//
fromTime = highs[hhIDX].time;
fromPrice = highs[hhIDX].value;
}
//
// Check Requirements for Trend ...
has =
NotEmptyZero(toPrice) &&
NotEmptyZero(fromPrice) &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime);
if (has)
{
//
has = fima2Signaller.poiDrawer.DrawTrendLine(
fromPrice,
fromTime,
toPrice,
toTime,
zgTrendLine,
zgTrendName,
true // Ray Right ...
);
if (has)
{
zgTrendLine.Color(trendColor);
}
}
//
// Cleanup Resources ...
tmpBar.Clean();
}
//
if (!has)
{
SpecifiedClean(pivots);
}
}
//
// Cleanup Resources ...
SpecifiedClean(lows);
SpecifiedClean(highs);
}
//
// Draw Pivots ...
has = HasChild(pivots);
if (has)
{
//
CArrayObj *drawnPivots = new CArrayObj();
pivotsCount = fima2Signaller.poiDrawer.DrawPivots(
pivots,
drawnPivots //
);
}
//
// Cleanup Resources ...
SpecifiedClean(pivots);
}
//
// Support ...
bool hasSupport = marketStructure.support.IsValid();
if (hasSupport)
{
//
AddIfNotExists(
marketStructure.support,
supports //
);
//
XCBoxObject *iObj;
has = fima2Signaller.poiDrawer.DrawBox(
marketStructure.support,
iObj);
if (has)
{
}
}
//
// Resistance ...
bool hasResistance = marketStructure.resistance.IsValid();
if (hasResistance)
{
//
AddIfNotExists(
marketStructure.resistance,
resistances //
);
//
XCBoxObject *iObj;
has = fima2Signaller.poiDrawer.DrawBox(
marketStructure.resistance,
iObj);
if (has)
{
}
}
//
// Check Bar Pattern Exists ...
has = hasPinnedBar ||
hasEngulfedBar ||
hasFlagPattern ||
hasStarPattern ||
hasSignalKeyBar ||
hasRisingPattern ||
hasPiercingPattern;
//
// Select Pattern Direction and Price and Price Type ...
if (has)
{
//
if (hasPinnedBar)
{
//
iDir = marketStructure.pinnedDir;
iName = "pinned" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasEngulfedBar)
{
//
iDir = marketStructure.engulfedDir;
iName = "engulfed" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasFlagPattern)
{
//
iDir = marketStructure.flagPatternDir;
iName = "flagPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasStarPattern)
{
//
iDir = marketStructure.starPatternDir;
iName = "starPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasSignalKeyBar)
{
//
iDir = marketStructure.risingPatternDir;
iName = "risingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasRisingPattern)
{
//
iDir = marketStructure.piercingPatternDir;
iName = "piercingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasPiercingPattern)
{
//
iDir = marketStructure.signalKeyBarPatternDir;
iName = "signalKeyBarPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
}
//
isBullish = IsSpecifiedBullish(iDir);
//
// Retrieve Price Type for Validate ...
iPriceType = isBullish
? X_PRICE_LOW
: X_PRICE_HIGH;
iPrice = bar.GetPrice(iPriceType);
//
has = HasDirection(iDir);
}
//
// Validate Patterns based on MA Band ...
if (has)
{
//
// Retrieve MA Band for Validation ...
double iMABandUpper = fima2Signaller.fimaHelper.GetMABandUpper(barIndex);
double iMABandLower = fima2Signaller.fimaHelper.GetMABandLower(barIndex);
//
// Validate ...
has = isBullish
? iPrice < iMABandLower
: iPrice > iMABandUpper;
}
//
// Select a Zone which Price inside it ...
//
// Validate Happens in Zone ...
int insideZoneIDX = -1;
has = has &&
(isBullish
? HasInside(
insideZoneIDX,
bar,
supports //
)
: HasInside(
insideZoneIDX,
bar,
resistances //
));
//
// Validate Selected Inside Zone ...
// whith Bars Edge ...
has = IsValidIndex(insideZoneIDX);
if (has)
{
//
if (isBullish)
{
iZone = supports[insideZoneIDX];
}
else
{
iZone = resistances[insideZoneIDX];
}
//
has = isBullish
? bar.high > supports[insideZoneIDX].upper
: bar.low < resistances[insideZoneIDX].lower;
}
//
// Checking Liquidities ...
//
// Draw Selected and Validated Bar and Selected Zone ...
if (has)
{
//
int iWidth = 1;
int iCode = 159;
color iClr = isBullish
? clrYellow
: clrDarkOrange;
ENUM_ARROW_ANCHOR iAnchor = isBullish
? ANCHOR_TOP
: ANCHOR_BOTTOM;
//
XCBoxObject *iZoneObj;
XCBarArrowObject *iPatternObj;
//
has = fima2Signaller.poiDrawer.DrawBarArrow(
bar,
iPatternObj,
iPriceType,
iCode,
iClr,
iWidth,
iAnchor,
iName,
true, // Ignore Bar Tag ...
10 // Threshold ...
);
if (has)
{
}
//
has = fima2Signaller.poiDrawer.DrawBox(
iZone,
iZoneObj,
true, // Ignore At ...
iZone.type // Name ...
);
if (has)
{
//
XPOIStyle iStyle;
fima2Signaller.poiDrawer.GetBoxStyle(
iStyle,
iZone.dir //
);
iStyle.width = 2;
iStyle.clr = iClr;
fima2Signaller.poiDrawer.ApplyBoxStyle(
iZoneObj,
iStyle //
);
}
}
//
// Preparing Signal ...
if (has)
{
//
iSignal.time = bar.time;
iSignal.provider = "XFima";
iSignal.symbol = bar.symbol;
iSignal.period = bar.period;
iSignal.mode = X_ORDER_MODE_MARKET;
iSignal.entry = GetEntry(bar.symbol, iDir);
iSignal.type = isBullish
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
//
iSignal.volume = 0.01;
//
double _r2r = 2.0;
double _slDistanceInPoint = 5;
double _point = GetPoints(iSignal.symbol);
double _riskDistance = _slDistanceInPoint * _point;
double _risk = _riskDistance + MathAbs((isBullish ? iZone.lower : iZone.upper) - iSignal.entry);
double _reward = GetSpread(iSignal.symbol) + (_risk * _r2r);
//
double sl = isBullish
? iSignal.entry - _risk
: iSignal.entry + _risk;
double tp = isBullish
? iSignal.entry + _reward
: iSignal.entry - _reward;
//
iSignal.sl = sl;
iSignal.tp = tp;
//
has = iSignal.IsValid();
if (has)
{
//
XCSignalObject *iSignalObj;
has = fima2Signaller.poiDrawer.DrawSignal(
iSignal,
iSignalObj,
7 //
);
}
}
//
// For Logging ...
if (has)
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT eResult;
has = eaExpert.eaTrader.ExecuteSignal(iSignal, eResult);
Print("Detect a Potential Place for Price Movement: ", ToXString(iDir), ", Time: ", bar.time);
}
//
// Cleanup Resources ...
iZone.Clean();
iSignal.Clean();
SpecifiedClean(supports);
SpecifiedClean(resistances);
}
//
void HandleLookupSignal(XOHCL &bar)
{
//
bool has =
bar.IsValid();
if (!has)
{
return;
}
//
XBoxZone iZone;
XSignal iSignal;
string iName = NULL;
bool isBullish = false;
bool isBearish = false;
int barIndex = bar.Index();
double iPrice = EMPTY_VALUE;
XFIMAConditions fimaConditions;
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
int cIDX = 0;
int pIDX = cIDX + 1;
//
// Check for a Cross ...
//
// fima2Signaller.fimaHelper.Update(barIndex);
has = fima2Signaller.fimaHelper.GetConditions(
fimaConditions,
barIndex,
5 //
);
//
double cSlowMA = fimaConditions.maSlowBuffer[cIDX];
double pSlowMA = fimaConditions.maSlowBuffer[pIDX];
//
double cMAUpper = fimaConditions.maBandUpperBuffer[cIDX];
double cMALower = fimaConditions.maBandLowerBuffer[cIDX];
//
double pMAUpper = fimaConditions.maBandUpperBuffer[pIDX];
double pMALower = fimaConditions.maBandLowerBuffer[pIDX];
//
bool isCrossedOver = cSlowMA > cMALower &&
pSlowMA < pMALower;
//
bool isCrossedUnder = cSlowMA < cMAUpper &&
cSlowMA > pMAUpper;
//
has = isCrossedOver ||
isCrossedUnder;
if (!has)
{
//
isBullish = false;
isBearish = false;
iDir = X_DIRECTION_NONE;
}
//
if (has)
{
//
isBullish = isCrossedOver;
isBearish = isCrossedUnder;
}
//
iDir = (isBullish && !isBearish)
? X_DIRECTION_BULLISH
: (isBearish && !isBullish)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(iDir);
if (has)
{
Print("Conditions Detected ...");
}
//
// Cleanup Resources ...
fimaConditions.Clean();
}
//