diff --git a/Classes/x-saherelm.x121.provider.class.mq5 b/Classes/x-saherelm.x121.provider.class.mq5 index a84ea75a..207f8b54 100644 --- a/Classes/x-saherelm.x121.provider.class.mq5 +++ b/Classes/x-saherelm.x121.provider.class.mq5 @@ -3398,7 +3398,7 @@ public: // // - double cPeak = cMarket.pv.GetPeak(0); + double cPVPeak = cMarket.pv.GetPeak(0); double sPeak = sMarket.pv.GetPeak(0); double mPeak = mMarket.pv.GetPeak(0); double lPeak = lMarket.pv.GetPeak(0); @@ -3406,7 +3406,7 @@ public: // double mPeaks[] = { - cPeak, + cPVPeak, sPeak, mPeak, lPeak, @@ -3418,7 +3418,7 @@ public: { // Remove( - cPeak, + cPVPeak, mPeaks // ); } @@ -3440,7 +3440,7 @@ public: Clean(vales); // - double cVale = cMarket.pv.GetVale(0); + double cPVVale = cMarket.pv.GetVale(0); double sVale = sMarket.pv.GetVale(0); double mVale = mMarket.pv.GetVale(0); double lVale = lMarket.pv.GetVale(0); @@ -3448,7 +3448,7 @@ public: // double mVales[] = { - cVale, + cPVVale, sVale, mVale, lVale, @@ -3460,7 +3460,7 @@ public: { // Remove( - cVale, + cPVVale, mVales // ); } @@ -7571,20 +7571,420 @@ private: bool result = false; // - // XDON - // XCHE + // XSTR // XPV // XHK + // XCHE // XTD + // XDON // // Conditions ... - // - [] Candle Crossed Down XDON HL (High Lower); - // - [] Candle Crossed Up XDON HL (High Lower); - // - [] Wait Until XTD Bullish Crossed Up Bearish; - // - [] When Candle Crossed Up XTD Must in Bearish Mode; - // - [] Check CHE Long Exits Exists; - // - [] Check STR Trend is Bullish; + // - [] XPV,XDON: XPV Vale and XDON LL (Low Lower) must be same; + // - [] XDON: Candle Crossed Down XDON HL (High Lower); + // - [] XDON: Candle Crossed Up XDON HL (High Lower); + // - [] XTD: When Candle Crossed Up XTD Must in Bullish Mode; + // - [] XCHE: Check CHE Long Exits Exists; + // - [] XSTR: Check STR Trend is Bullish; + // - [] XPV: Not In Fibo Section Changed; + // - [] XPV: Fibo Level 5 Crossed Using Don HL Crosser Cndle; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + + // + // XSTR ... + ENUM_XSTR_TREND_STATES cStrState = cMarket + .str + .GetState(cIndex); + double cStrTrend = cMarket.str.GetTrend(cIndex); + bool isCStrBullish = cStrState == X_STR_BULLISH; + bool isCStrBearish = cStrState == X_STR_BEARISH; + + // + ENUM_XSTR_TREND_STATES pStrState = cMarket + .str + .GetState(pIndex); + double pStrTrend = cMarket.str.GetTrend(pIndex); + bool isPStrBullish = pStrState == X_STR_BULLISH; + bool isPStrBearish = pStrState == X_STR_BEARISH; + + // + bool isTrendBullish = isCStrBullish; + bool isTrendBearish = isCStrBearish; + + // + bool isTrendSwitchedToBullish = + // + isCStrBullish && + !isPStrBullish + // + ; + + // + bool isTrendSwitchedToBearish = + // + isCStrBearish && + !isPStrBearish + // + ; + + // + // XCHE ... + + // + double cCHELongExit1 = cMarket.che.GetLongExit1(cIndex); + double cCHELongExit2 = cMarket.che.GetLongExit2(cIndex); + + // + double pCHELongExit1 = cMarket.che.GetLongExit1(pIndex); + double pCHELongExit2 = cMarket.che.GetLongExit2(pIndex); + + // + double cCHEShortExit1 = cMarket.che.GetShortExit1(cIndex); + double cCHEShortExit2 = cMarket.che.GetShortExit2(cIndex); + + // + double pCHEShortExit1 = cMarket.che.GetShortExit1(pIndex); + double pCHEShortExit2 = cMarket.che.GetShortExit2(pIndex); + + // + bool CCHEHasLongExit1 = NotEmpty(cCHELongExit1); + bool CCHEHasLongExit2 = NotEmpty(cCHELongExit2); + + // + bool CCHEHasShortExit1 = NotEmpty(cCHEShortExit1); + bool CCHEHasShortExit2 = NotEmpty(cCHEShortExit2); + + // + bool PCHEHasLongExit1 = NotEmpty(pCHELongExit1); + bool PCHEHasLongExit2 = NotEmpty(pCHELongExit2); + + // + bool PCHEHasShortExit1 = NotEmpty(pCHEShortExit1); + bool PCHEHasShortExit2 = NotEmpty(pCHEShortExit2); + + // + bool isCCHEBullish = + // + CCHEHasLongExit1 && + CCHEHasLongExit2 + // + ; + + // + bool isCCHEBearish = + // + CCHEHasShortExit1 && + CCHEHasShortExit2 + // + ; + + // + bool isPCHEBullish = + // + PCHEHasLongExit1 && + PCHEHasLongExit2 + // + ; + + // + bool isPCHEBearish = + // + PCHEHasShortExit1 && + PCHEHasShortExit2 + // + ; + + // + bool isCHEBullish = isCCHEBullish; + bool isCHEBearish = isCCHEBearish; + bool isCHESwitchedToBullish = + // + isCCHEBullish && + !isPCHEBullish + // + ; + bool isCHESwitchedToBearish = + // + isCCHEBearish && + !isPCHEBearish + // + ; + + // + // XPV ... + + double cPVPeak = cMarket.pv.GetPeak(cIndex); + double cPVVale = cMarket.pv.GetVale(cIndex); + + // + double pPVPeak = cMarket.pv.GetPeak(pIndex); + double pPVVale = cMarket.pv.GetVale(pIndex); + + // + double cPVSup = cMarket.pv.GetSupport(cIndex); + double pPVSup = cMarket.pv.GetSupport(pIndex); + + // + double cPVRes = cMarket.pv.GetResistance(cIndex); + double pPVRes = cMarket.pv.GetResistance(pIndex); + + // + double cPVFib1 = cMarket.pv.GetFib1(cIndex); + double cPVFib2 = cMarket.pv.GetFib2(cIndex); + double cPVFib3 = cMarket.pv.GetFib3(cIndex); + double cPVFib4 = cMarket.pv.GetFib4(cIndex); + double cPVFib5 = cMarket.pv.GetFib5(cIndex); + + // + double pPVFib1 = cMarket.pv.GetFib1(pIndex); + double pPVFib2 = cMarket.pv.GetFib2(pIndex); + double pPVFib3 = cMarket.pv.GetFib3(pIndex); + double pPVFib4 = cMarket.pv.GetFib4(pIndex); + double pPVFib5 = cMarket.pv.GetFib5(pIndex); + + // + bool isNewPeak = cPVPeak != pPVPeak; + bool isNewPeakUnderLast = + // + isNewPeak && + cPVPeak < pPVPeak + // + ; + bool isNewPeakOverLast = + // + isNewPeak && + cPVPeak > pPVPeak + // + ; + + // + bool isNewVale = cPVVale != pPVVale; + bool isNewValeUnderLast = + // + isNewVale && + cPVVale < pPVVale + // + ; + bool isNewValeOverLast = + // + isNewVale && + cPVVale > pPVVale + // + ; + + // + bool isFiboIncreased = + // + cPVFib1 > pPVFib1 && + cPVFib2 > pPVFib2 && + cPVFib3 > pPVFib3 && + cPVFib4 > pPVFib4 && + cPVFib5 > pPVFib5 + // + ; + + // + bool isFiboDecreased = + // + cPVFib1 < pPVFib1 && + cPVFib2 < pPVFib2 && + cPVFib3 < pPVFib3 && + cPVFib4 < pPVFib4 && + cPVFib5 < pPVFib5 + // + ; + + // + bool isFiboSectionChanged = + // + (isFiboDecreased && + isNewPeakUnderLast) + // + || + // + (isFiboIncreased && + isNewValeOverLast) + // + ; + + // + // XFI ... + + // + double cFI = fiHelper.GetMain(cIndex); + double pFI = fiHelper.GetMain(pIndex); + + // + bool isCFIOverZero = cFI > 0; + bool isCFIUnderZero = cFI > 0; + + // + bool isPFIOverZero = pFI > 0; + bool isPFIUnderZero = pFI > 0; + + // + bool isFICrossedOverZero = + // + isCFIOverZero && + !isPFIOverZero + // + ; + + // + bool isFICrossedUnderZero = + // + isCFIUnderZero && + !isPFIUnderZero + // + ; + + // + // XHK ... + + // + XOHCL cSMHKBar; + cMarket.hk.SMAsOHCL( + cSMHKBar, + cIndex // + ); + + // + XOHCL pSMHKBar; + cMarket.hk.SMAsOHCL( + pSMHKBar, + pIndex // + ); + + // + bool isCSMHKBullish = cSMHKBar.IsBullish(); + bool isCSMHKBearish = cSMHKBar.IsBearish(); + + // + bool isPSMHKBullish = pSMHKBar.IsBullish(); + bool isPSMHKBearish = pSMHKBar.IsBearish(); + + // + bool isSMHKSwitchedToBullish = + // + isCSMHKBullish && + isPSMHKBearish + // + ; + + // + bool isSMHKSwitchedToBearish = + // + isCSMHKBearish && + isPSMHKBullish + // + ; + + // + // XTD ... + + // + double cTDBullish = tdHelper.GetBullish(cIndex); + double pTDBullish = tdHelper.GetBullish(pIndex); + + // + double cTDBearish = tdHelper.GetBearish(cIndex); + double pTDBearish = tdHelper.GetBearish(pIndex); + + // + bool isCTDBullish = + // + cTDBullish > cTDBearish + // + ; + + // + bool isCTDBearish = + // + cTDBearish > cTDBullish + // + ; + + // + bool isPTDBullish = + // + pTDBullish > pTDBearish + // + ; + + // + bool isPTDBearish = + // + pTDBearish > pTDBullish + // + ; + + // + bool isTDBullish = isCTDBullish; + bool isTDBearish = isCTDBearish; + bool isTDSwitchedToBullish = + // + isCTDBullish && + !isPTDBullish + // + ; + bool isTDSwitchedToBearsih = + // + isCTDBearish && + !isPTDBearish + // + ; + + // + // XDON ... + + // + XOHCL cBar = cMarket.GetBar(cIndex); + XOHCL pBar = cMarket.GetBar(pIndex); + + // + double cDONUpperOpen = cMarket.don.GetUpperO(cIndex); + double cDONUpperClose = cMarket.don.GetUpperC(cIndex); + double cDONUpperHigh = cMarket.don.GetUpperH(cIndex); + double cDONUpperLow = cMarket.don.GetUpperL(cIndex); + + // + double cDONLowerOpen = cMarket.don.GetLowerO(cIndex); + double cDONLowerClose = cMarket.don.GetLowerC(cIndex); + double cDONLowerHigh = cMarket.don.GetLowerH(cIndex); + double cDONLowerLow = cMarket.don.GetLowerL(cIndex); + + // + double pDONUpperOpen = cMarket.don.GetUpperO(pIndex); + double pDONUpperClose = cMarket.don.GetUpperC(pIndex); + double pDONUpperHigh = cMarket.don.GetUpperH(pIndex); + double pDONUpperLow = cMarket.don.GetUpperL(pIndex); + + // + double pDONLowerOpen = cMarket.don.GetLowerO(pIndex); + double pDONLowerClose = cMarket.don.GetLowerC(pIndex); + double pDONLowerHigh = cMarket.don.GetLowerH(pIndex); + double pDONLowerLow = cMarket.don.GetLowerL(pIndex); + + // + bool isBarCrossedDownDONLowerHigh = + // + cBar.IsBreakDown(pDONLowerHigh) + // + ; + + // + result = + // + isTrendSwitchedToBullish + // + ; + if (result) { + Print("Salam"); + } // return result; @@ -7819,7 +8219,6 @@ private: // ; - // result = // @@ -8701,7 +9100,7 @@ private: bullScore, bearScore // ); - + // double bearScoreAVG3 = GetBearishScoreAverage(1, 3); double bullScoreAVG100 = GetBullishScoreAverage(1, 100); diff --git a/Experts/x-test.x121ea.mq5 b/Experts/x-test.x121ea.mq5 index f1621b9d..8f7407ba 100644 --- a/Experts/x-test.x121ea.mq5 +++ b/Experts/x-test.x121ea.mq5 @@ -40,7 +40,7 @@ bool x121EAAllowShort = true; // Allow Short Trades int x121EAManageInterval = 0; // Manager Check Intervals Seconds int x121EAMaxAllowedPositions = 5; // Max Allowed Positions double x121EAMaxAllowedSpread = 0; // Max Allowed Spred for Opening Trades -double x121EAMinProfitPerTrade = 1; // Min Profit Per Trade based On Volume Factor (Hedge) +double x121EAMinProfitPerTrade = 3; // Min Profit Per Trade based On Volume Factor (Hedge) double x121EAMinProfitPerVolumeFactor = 0.01; // Min Volume Factor for Calculating Profit (Hedge) double x121EAMaxAllowedDrawdownFactor = 0.002; // Max Allowed Drawdown Factor // diff --git a/Indicators/x-saherelm.xfi.osc.mq5 b/Indicators/x-saherelm.xfi.osc.mq5 new file mode 100644 index 00000000..0e7edc54 --- /dev/null +++ b/Indicators/x-saherelm.xfi.osc.mq5 @@ -0,0 +1,309 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator +// --------------------------------------------- +// Name: XFI +// Description: Price Momentum Power Detection +// Market Analysor ... +// +// +// 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 XFI Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XFI" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 18; // Length +input ENUM_MA_METHOD method = MODE_SMA; // MA Method +input ENUM_APPLIED_VOLUME appliedTo = VOLUME_TICK; // Applied To +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_separate_window +// #property indicator_chart_window + +// +#property indicator_buffers 2 +#property indicator_plots 1 +// #property indicator_plots 0 + +// +// FI Buffer ... +#define fiBufferIndex 0 +#define fiColorBufferIndex 1 + +// +double fiBuffer[]; +double fiColorBuffer[]; + +// +#property indicator_label1 "XFI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int fiHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + fiHandler = iForce( + _Symbol, + _Period, + length, + method, + appliedTo); + if (fiHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // 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 ... + IndicatorRelease(fiHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + // Check Calculated Bars ... + int fiCalculatedBars = BarsCalculated(fiHandler); + if (fiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFis = CopyBuffer(fiHandler, 0, 0, limit, fiBuffer); + if (copiedFis <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string fiBufferLabel = "XFI " + "(" + (string)length + ")"; + + // + // FI Buffer ... + ArraySetAsSeries(fiBuffer, true); + // SetIndexBuffer(fiBufferIndex, fiBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(fiBufferIndex, fiBuffer, INDICATOR_DATA); + PlotIndexSetString(fiBufferIndex, PLOT_LABEL, fiBufferLabel); + + // + // FI Color Buffer ... + ArraySetAsSeries(fiColorBuffer, true); + SetIndexBuffer(fiColorBufferIndex, fiColorBuffer, INDICATOR_COLOR_INDEX); + // SetIndexBuffer(fiColorBufferIndex, fiColorBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + double iValue = fiBuffer[bar_index]; + + // + double iColorIndex = + iValue > 0 ? 0 : iValue < 0 ? 2 + : 1; + + // + // Set Buffer Color Index ... + fiColorBuffer[bar_index] = iColorIndex; +} +// +// END Functions ... +// diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 2c2ad194..4968d755 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -853,6 +853,33 @@ struct XOHCL return result; } + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + return result; + } + // // Check Bar has Strong Body or Not ... bool HasStrongBody() @@ -877,6 +904,239 @@ struct XOHCL return result; } + // + // Bar Must Open Below Prce + // and Close Above it ... + bool IsBreakUp( + double price // a Price to Check Breake + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + result = + // + close > price && + open < price; + + // + return result; + } + + // + // Bar Must Open Above Prce + // and Close Below it ... + bool IsBreakDown( + double price // a Price to Check Breake + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + result = + // + open > price && + close < price; + + // + return result; + } + + // + bool IsBreakOut( + double price, // a Price to Check Breake + bool useHighLow = true // if true using High and Low price for Breakeouts, if not use Open Close + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + double selectedUp = + useHighLow + ? high + : GetUp(); + double selectedDown = + useHighLow + ? low + : GetDown(); + + // + result = + // + selectedUp > price && + selectedDown < price; + + // + return result; + } + + // + // Check Bar is Inside Previus Bar ... + bool IsInsideBar( + double threshold = 5 // Points Distance between Up and Down + ) + { + // + bool result = false; + + // + if (threshold < 0) + { + threshold = 0; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double offset = PointToPrice(threshold, this.symbol); + + // + result = + // + pBar.high > this.high && + pBar.low < this.low && + MathAbs(pBar.low - this.low) > offset && + MathAbs(pBar.high - this.high) > offset + // + ; + + // + return result; + } + + // + // Check Bar has Strongest Body in a Range ... + bool HasStrongestBody( + int loopback = 3 // loopback candles to compare it ... + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double body = GetBody(); + XOHCL prev = this; + for (int i = 0; i < loopback; i++) + { + // + bool isValid = prev.GetPreviousBar(prev); + if (!isValid) + { + // + result = false; + break; + } + + // + result = + // + result && + body > prev.GetBody() + // + ; + if (!result) + { + break; + } + } + + // + return result; + } + + // + // Check Bar has Weakest Body in a Range ... + bool HasWeakestBody( + int loopback = 3 // loopback candles to compare it ... + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double body = GetBody(); + XOHCL prev = this; + for (int i = 0; i < loopback; i++) + { + // + bool isValid = prev.GetPreviousBar(prev); + if (!isValid) + { + // + result = false; + break; + } + + // + result = + // + result && + body < prev.GetBody() + // + ; + if (!result) + { + break; + } + } + + // + return result; + } + // // Determines Swings based On this Bar ... // Calculates Based on atleast 3 Bars Prev ...