// // // // Detect At lease Two PEAK and Two Vale ... // XZigZagPoint tmpPoints[]; // Copy( // points, // tmpPoints // // ); // // // // Detect Highs ... // // // // Highest High ... // // // XZigZagPoint iZGPeak1; // XZigZagPoint iZGPeak2; // // // // First ... // int idx = GetHighest( // tmpPoints, // X_ZIGZAG_POINT_TYPE_PEAK // // ); // result = IsValidIndex(idx); // if (!result) // { // // // Clean(); // iZGPeak1.Clean(); // iZGPeak2.Clean(); // SpecifiedClean(tmpPoints); // // // return result; // } // iZGPeak1 = tmpPoints[idx]; // ArrayRemove( // tmpPoints, // idx, // 1 // // ); // // // // Second ... // idx = GetHighest( // tmpPoints, // X_ZIGZAG_POINT_TYPE_PEAK // // ); // result = IsValidIndex(idx); // if (!result) // { // // // Clean(); // iZGPeak1.Clean(); // iZGPeak2.Clean(); // SpecifiedClean(tmpPoints); // // // return result; // } // iZGPeak2 = tmpPoints[idx]; // ArrayRemove( // tmpPoints, // idx, // 1 // // ); // // // // Detect Lows ... // // // XZigZagPoint iZGVale1; // XZigZagPoint iZGVale2; // // // // First ... // idx = GetLowest( // tmpPoints, // X_ZIGZAG_POINT_TYPE_VALE // // ); // result = IsValidIndex(idx); // if (!result) // { // // // Clean(); // iZGPeak1.Clean(); // iZGPeak2.Clean(); // iZGVale1.Clean(); // iZGVale2.Clean(); // SpecifiedClean(tmpPoints); // // // return result; // } // iZGVale1 = tmpPoints[idx]; // ArrayRemove( // tmpPoints, // idx, // 1 // // ); // // // // Second ... // idx = GetLowest( // tmpPoints, // X_ZIGZAG_POINT_TYPE_VALE // // ); // result = IsValidIndex(idx); // if (!result) // { // // // Clean(); // iZGPeak1.Clean(); // iZGPeak2.Clean(); // iZGVale1.Clean(); // iZGVale2.Clean(); // SpecifiedClean(tmpPoints); // // // return result; // } // iZGVale2 = tmpPoints[idx]; // ArrayRemove( // tmpPoints, // idx, // 1 // // ); // // // // Check Directions ... // bool isBullish = // // // (iZGPeak1.time > iZGPeak2.time && // iZGVale1.time < iZGVale2.time) // // // ; // bool isBearish = // // // (iZGPeak1.time < iZGPeak2.time && // iZGVale1.time > iZGVale2.time) // // // ; // result = // (isBullish && !isBearish) || // (isBearish && !isBullish); // if (!result) // { // // // Clean(); // iZGPeak1.Clean(); // iZGPeak2.Clean(); // iZGVale1.Clean(); // iZGVale2.Clean(); // SpecifiedClean(tmpPoints); // // // return result; // } // // // // Setting Direction ... // dir = // isBullish // ? X_DIRECTION_BULLISH // : isBearish // ? X_DIRECTION_BEARISH // : X_DIRECTION_NONE; // // // // Setting Points ... // Copy( // points, // pivots // // ); // // Cleanup Resources ... // iZGPeak1.Clean(); // iZGPeak2.Clean(); // iZGVale1.Clean(); // iZGVale2.Clean(); // SpecifiedClean(tmpPoints); /** * Analyse Market Structure ... * * @param bar: XOHCL, Specified Bar ... * @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ... * * @return ( bool ) */ bool Analyse( XOHCL &bar, XZigZagPivot &_pivots[] // ) { // bool result = false; // // Validate ... result = bar.IsValid() && HasChild(_pivots) && bar.symbol == _pivots[0].symbol; if (!result) { // Clean(); return result; } // // AssignSymbol and Period ... time = bar.time; symbol = bar.symbol; period = bar.period; Copy(_pivots, pivots); // // Calculate Peaks and Vales Regressions ... // // Peaks Processing ... double mPeak = 0; double bPeak = 0; result = ValidateZigZagPivots( mPeak, bPeak, _pivots, X_ZIGZAG_PIVOT_TYPE_PEAK // ); // // Vales Processing ... double mVale = 0; double bVale = 0; result = result && ValidateZigZagPivots( mVale, bVale, _pivots, X_ZIGZAG_PIVOT_TYPE_VALE // ); if (!result) { // Clean(); // SpecifiedClean(recentPeaks); // SpecifiedClean(recentVales); // return result; } // // // // Extracting Pivots ... // int numberOfPivots = 2; // // // // Reading Recent Peaks ... // XZigZagPivot recentPeaks[]; // int recentPeaksCount = GetRecent( // _pivots, // recentPeaks, // numberOfPivots, // X_ZIGZAG_PIVOT_TYPE_PEAK // // ); // // // // Reading Recent Vales ... // XZigZagPivot recentVales[]; // int recentValesCount = GetRecent( // _pivots, // recentVales, // numberOfPivots, // X_ZIGZAG_PIVOT_TYPE_VALE // // ); // // // // Validate Pivots ... // result = // recentPeaksCount >= numberOfPivots && // recentValesCount >= numberOfPivots; // if (!result) // { // // // Clean(); // SpecifiedClean(recentPeaks); // SpecifiedClean(recentVales); // // // return result; // } // // // // Detect Direction ... // // // int zIdx = 0; // int pIdx = numberOfPivots - 1; // // // bool isBullish = // recentPeaks[zIdx].value > recentPeaks[pIdx].value && // recentVales[zIdx].value > recentVales[pIdx].value; // // // bool isBearish = // recentPeaks[zIdx].value < recentPeaks[pIdx].value && // recentVales[zIdx].value < recentVales[pIdx].value; // // // result = isBullish || isBearish; // if (!result) // { // // // Clean(); // SpecifiedClean(recentPeaks); // SpecifiedClean(recentVales); // // // return result; // } // // // dir = // isBullish // ? X_DIRECTION_BULLISH // : X_DIRECTION_BEARISH; // // Calculate Support and Resistance ... // // Validate ... result = IsValid(); if (!result) { Clean(); } // // SpecifiedClean(recentPeaks); // SpecifiedClean(recentVales); // return result; } bool ValidateZigZagPivots( double &_pivot, double &_processed, XZigZagPivot &_pivots[], ENUM_X_ZIGZAG_POINT_TYPE _type // ) { // bool result = false; // // Prepare ... _pivot = 0; _processed = 0; // // Validate ... result = HasChild(_pivots); if (!result) { return result; } // // Define Required Variables for Calculations ... double sumT = 0; double sumP = 0; double sumTP = 0; double sumT2 = 0; bool has = false; int typeCount = 0; // // Loop Through Pivots to Calculate Specified // Type Pivots Summaries ... int count = ArraySize(_pivots); for (int i = 0; i < count; i++) { // // Check Type Passed ... has = !IsXValid(_type) ? true : _type == _pivots[i].type; if (!has) { continue; } // typeCount++; double iP = _pivots[i].value; double iT = (double)_pivots[i].time; // sumT += iT; sumP += iP; sumTP += iT * iP; sumT2 += iT * iP; } // // Calculate Process Values ... double denominator = typeCount * sumT2 - sumT * sumT; if (denominator != 0) { // _pivot = (typeCount * sumTP - sumT * sumP) / denominator; _processed = (sumP - _pivot * sumT) / typeCount; } else { _processed = sumP / typeCount; } // // Validating Result ... result = _pivot > 0 && _processed > 0; // return result; } /** * Analyse Market Structure ... * * @param bar: XOHCL, Specified Bar ... * @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ... * * @return ( bool ) */ bool Analyse( XOHCL &bar, XZigZagPivot &_pivots[] // ) { // bool result = false; // // Validate ... result = bar.IsValid() && HasChild(_pivots) && bar.symbol == _pivots[0].symbol; if (!result) { // Clean(); return result; } // // Assign Requirements ... // time = bar.time; symbol = bar.symbol; period = bar.period; Copy(_pivots, pivots); // int oldestPeakIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_PEAK); int oldestValeIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE); int youngestPeakIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_PEAK); int youngestValeIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE); // // Calculate Peaks and Vales Regressions ... // // Peaks Processing ... double mPeak = 0; double bPeak = 0; bool hasPeak = ValidateZigZagPivots( mPeak, bPeak, pivots, X_ZIGZAG_PIVOT_TYPE_PEAK // ); // // Vales Processing ... double mVale = 0; double bVale = 0; bool hasVale = ValidateZigZagPivots( mVale, bVale, pivots, X_ZIGZAG_PIVOT_TYPE_VALE // ); // // Validate Calculated requirements ... result = (hasPeak || hasVale) && (IsValidIndex(oldestPeakIdx) && IsValidIndex(oldestValeIdx) && IsValidIndex(youngestPeakIdx) && IsValidIndex(youngestValeIdx)); if (!result) { // Clean(); return result; } // // Calculating Values ... // peakToTime = pivots[youngestPeakIdx].time; peakFromTime = pivots[oldestPeakIdx].time; // valeToTime = pivots[youngestValeIdx].time; valeFromTime = pivots[oldestValeIdx].time; // // Check Different Senarios ... // 1-Valid Peak and Valid Vale Exists ... if (hasPeak && hasVale) { // // When Slopes Have same Sign, Use Average Slope for Parallel Lines ... if (mPeak * mVale > 0) { // // Calculating Parallel Slopes ... double slopeParallel = (mPeak + mVale) / 2; double bParallelPeak = pivots[youngestPeakIdx].value - slopeParallel * (double)peakToTime; double bParallelVale = pivots[youngestValeIdx].value - slopeParallel * (double)valeToTime; // // Peak ... peakTo = slopeParallel * (double)peakToTime + bParallelPeak; peakFrom = slopeParallel * (double)peakFromTime + bParallelPeak; // // Vale ... valeTo = slopeParallel * (double)valeToTime + bParallelVale; valeFrom = slopeParallel * (double)valeFromTime + bParallelVale; } else // // separate trendlines if slopes differ ... { // // Peak ... peakTo = mPeak * (double)peakToTime + bPeak; peakFrom = mPeak * (double)peakFromTime + bPeak; // // Vale ... valeTo = mVale * (double)valeToTime + bVale; valeFrom = mVale * (double)valeFromTime + bVale; } } else // // Only one of them Exists ... { // // Valid Peak ... if (hasPeak) { // // Peak ... peakTo = mPeak * (double)peakToTime + bPeak; peakFrom = mPeak * (double)peakFromTime + bPeak; } // // Valid Vale ... if (hasVale) { // // Vale ... valeTo = mVale * (double)valeToTime + bVale; valeFrom = mVale * (double)valeFromTime + bVale; } } // // Detecting Direction ... // bool isBullish = valeTo > valeFrom || (valeTo > valeFrom && peakTo > peakFrom); // bool isBearish = peakTo < peakFrom || (peakTo < peakFrom && valeTo < valeFrom); // // Validate When Only One Direction Exists ... result = (isBullish && !isBearish) || (isBearish && !isBullish); if (!result) { // Clean(); return result; } // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Calculate Support and Resistance ... // // Validate ... result = IsValid(); if (!result) { Clean(); } // return result; }