Neo-Fractals for AmiBroker Community
First and foremost, I would like to acknowledge two experts "Mr. @empottasch and Mr. @JohnHT" whose work has significantly contributed to this project. The codes I utilized from this forum were originally created by them, and they deserve full credit for their efforts. Special thanks to Mr. @empottasch and Mr. @JohnHT. Despite having a logical understanding of the solution, my current level of AFL (AmiBroker Formula Language) knowledge would not have allowed me to practically implement it without their codes.
Further, I warmly welcome any expert who wishes to contribute to enhancing the performance or adding features to this code. Your contributions would be greatly appreciated.
Introductory Comment:
Here, I introduce a completely new type of fractals, which I have named 'Neo-Fractals'. These Neo-Fractals offer a fresh approach compared to traditional fractals and may be of interest to traders.
It's common knowledge among technical analysts that a zigzag based on fractals is the best choice if you want to maximize the number of peaks and troughs. This is beneficial for pattern detection, as more peaks and troughs increase the number of detectable patterns. However, too many peaks and troughs can clutter the chart and generate patterns too small to be useful. To address this, I have used an existing fractal code taken from one of Mr. @empottasch's online code that employs HHV (Highest High Value) and LLV (Lowest Low Value) functions, and modified it to suit my needs. After using that code, it still generates a great number of peaks and troughs, but not the extremely large number of peaks and troughs.
A Note on My English:
Being a monk and Ayurvedic doctor, untill a few past months, my focus has been mostly on Sanskrit texts and thereby -- inspite of being able to clearly understand the English without any single effort-- I lack in expressing myself in English. I heavily rely on online translators, so my expressions may not be clear. I appreciate your patience and effort.
Key Instructions:
The sequence of the three sections of this AFL code must not be altered. The three sections are named: "Clean Base Peak-Trough," "Find Missed Peak-Trough," and "Again Clean Peak-Trough." Additionally, the internal codes within the "Find Missed Peak-Trough" section must remain in their original order. Altering them might superficially seem to map price activity nicely, but it won't hold up upon closer inspection. I confirm this on the basis of a thorough examination of numerous charts across different time frames.
Solving Common Problems of ZigZags:
-
Alternating peaks-troughs and maintaining the accuracy of mapping:
One persistent problem with fractals is the inability to ensure that peaks and troughs alternate perfectly WHILE SIMULTANEOUSLY keeping the accuracy of the price-activity's mapping intact. This zigzag addresses this issue by utilizing Neo-Fractals, and then applying Mr. @empottasch's code to remove excess peak-and-trough signals. -
Missed pivots:
Second common issue with zigzags is that they occasionally miss marking a high or low that should be identified as a peak or trough. The solution involves first identifying such missed pivots and marking them correctly, followed by cleaning up excess peaks and troughs. I was fortunate to successfully code a method for this, and Mr. @JohnHT also shared a solution at the very same time. I opted to use Mr. @JohnHT's solution due to its superior performance and efficiency. Many thanks to Mr. @JohnHT for sharing his work.
One might wonder why zigzags miss these pivots. The explanation is complex and inherent to the nature of zigzags. No matter how peaks and troughs are defined, occasional skipping is inevitable. This issue can only be addressed after defining the peaks and troughs. For a visual example, you can refer to my posts here: Forum Link.
- Peak and Trough on the very same-bar:
A third problem is the issue of Peak and Trough being on the very same-bar. One mathematical solution to avoid this is to create a zigzag that skips all inside bars and then handle the outside bars. However, this approach has a significant drawback: if a large bar occurs, the zigzag will not map the price activity until the high or low of the large bar is crossed, ignoring the entire price activity within that range. The price activity within the range of large-bar is crucial for predicting price direction and estimating the minimum-distance price can travel in the direction of the breakout, especially when a trade is already has been placed and one needs to make a decision exit or remain in the market.
And if one ignores the above solution and simply let the zigzag to ignore such bars then it is going to require many number of bars ( numbers of bars required depend on the relative-size of large bar ) for the new peaks and troughs to freshly start the accurate mapping of the price-activity. Before this fresh stablization, one can not rely on those peaks and troughs. Therefore, it is very important that long bars which have both the peak & trough at their high and low are not skipped by the zigzag.
To address this, the Gfx functions are used in this zigzag to handle the bars where a peak and trough occur on the same bar. These functions connect the left and right pivots to such a bar and also show a vertical line covering the bar's length. The rest of the zigzag lines are generated without Gfx functions, making this a combination of regular and Gfx lines.
- Repainting fractals
Fractal peaks and troughs typically repaint, but this issue is largely resolved here. The exception is the very last leg, which remains uncertain and can repaint. However, ignoring this last leg, the recent zigzag leg before it does not repaint in the opposite direction, ensuring overall mapping accuracy. Ideally, I would like to code this last leg in a different color to indicate its uncertainty, but my current level of AFL (AmiBroker Formula Language) knowledge limiting me to practically implement it. I hope that some expert would come forward to help in this matter.
Final Thought:
Zigzags should not be used directly for trading. They are tools for mapping price activity and can lead to biases about future price direction. While zigzags are important to me, I always analyze a naked chart first, then view it with a zigzag plot. I suggest the same approach to everyone.
End Note:
If anyone is interested in understanding the rationale behind the Neo-Fractals, feel free to ask. The explanation may require several snapshots.
// AFL-Name: Neo-Fractals
// Author: @LotusHear ( Sunil Hooda aka Shivoham ) from https://forum.amibroker.com/
// Deticated: To AmiBroker Forum Community and to Mr.'Tomasz Janeczko' ( The owner & chief software architect of AmiBroker )
// Credits: All the credit goes to Mr. @empottasch ( Edward Pottasch ) and Mr. @JohnHT ( John Stone ) from https://forum.amibroker.com/
// Codes used in this AFL are the work of: Mr. @empottasch ( Edward Pottasch ) and Mr. @JohnHT ( John Stone )
// AFL Code Date: 12-July-2024
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_SECTION_BEGIN( "Date-Time etc." );
RequestTimedRefresh( 1 );
TTDC = ParamColor( "Title-Text's Default-Color", colorWhite );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MT_Start = BeginValue( BarIndex() );
MT_End = EndValue( BarIndex() );
MT_Periods = MT_End - MT_Start;
MT_ValueStart = BeginValue( C );
MT_ValueEnd = EndValue( C );
MT_Difference = MT_ValueEnd - MT_ValueStart;
MT_Percentage = NumToStr( ( ( MT_Difference / MT_ValueStart ) * 100 ), 1.2 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
function GetSecondNum()
{
Time = Now( 4 );
Seconds = int( Time % 100 );
Minutes = int( Time / 100 % 100 );
Hours = int( Time / 10000 % 100 );
SecondNum = int( Hours * 60 * 60 + Minutes * 60 + Seconds );
return SecondNum;
}
TimeFrame = Interval();
SecNumber = GetSecondNum();
NewPeriod = SecNumber % TimeFrame == 0;
SecsLeft = SecNumber - int( SecNumber / TimeFrame ) * TimeFrame;
SecsToGo = TimeFrame - SecsLeft;
if( NewPeriod )
{
Say( "New period" );
}
LastBar_Price = EndValue( Close );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SetChartOptions( 0, chartShowArrows | chartShowDates );
//TimeFrame = in1Minute * Param( "Time Frame (min)", 5, 1, 1440 * 10, 1 ); // 1440 minutes is 1 day
TimeFrame = in1Minute * Interval() / 60 * 1; // Param( "Chart Time Frame Factor", 1, 1, 10, 1 ); // factor 1 uses timeframe of chart
_N( Title = EncodeColor( TTDC ) + /* GfxSetTextColor(Text_Background_Color) + */ StrFormat( "Symbol-Name = {{NAME}} || Visible-Chart Date-&-Time = {{DATE}} || Open %g | High %g | Low %g | Close %g | ROC (%.1f%%) || " +
" Last-Price = " + LastBar_Price + "\n TimeFrame: " + TimeFrame / 60 + " Minutes | " + TimeFrame / 3600 + " Hours | " + TimeFrame / ( 3600 * 24 ) + " Days || " +
" Total-Bars = " + MT_Periods + " || Total %%Change = " + MT_Percentage + " || Current-Time = " + Now( 2 ) + " || CountDown to Bar-Close = " + SecsToGo +
"{{VALUES}} ", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// SetBarsRequired( -2, -2 );
Bi = BarIndex();
BC = BarCount - 1;
xCum = Cum( 1 );
FvB = FirstVisibleValue( Bi );
LvB = LastVisibleValue( Bi );
StartBar = BeginValue( Bi );
EndBar = EndValue( Bi );
SelectedBar = SelectedValue( Bi );
LastBar = LastValue( Bi );
SetBarsRequired( ( LvB - FvB ) * 4 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GraphXSpace = Param( "GraphXSpace", 10, 0, 100, 1 );
GraphLabelDecimals = Param( "Graph-Label's Decimals", 3, 0, 100, 1 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Font_Name = ParamList( "Font", "Tahoma|Helvetica|Arial Black|Verdana|Courier New|Times New Roman|Open Sans|Compact|Segoe UI|DejaVu Sans", 1 );
Text_Size = Param( "Text-Size", 8, 5, 20, 1 );
Text_Color = ParamColor( "Gfx Background-Color", colorWhite );
Plot( C, "Close", ParamColor( "Color", colorDefault ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_SECTION_BEGIN( "Price-Mode" );
PriceArrayMode_Switch = ParamToggle( "Use Close or High and Low price", "Use Close|Use High and Low", 1 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( PriceArrayMode_Switch == 1 )
{
PaH = High;
PaL = Low;
}
else
if( PriceArrayMode_Switch == 0 )
{
PaH = C;
PaL = C;
}
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_SECTION_BEGIN( "ZigZag Prameters" );
nZigZag_DisplaySwitch = ParamToggle( "Display Base-ZigZag ", "No|Yes", 1 );
nZZ_PeakTrough_Shapes_DisplaySwitch = ParamToggle( "Display ZZ's PeakTrough-Shapes", "No|Yes", 1 );
nPivot_Labels_DisplaySwitch = ParamToggle( "Display nPivot-Labels", "No|Yes", 1 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
pZigZag_DisplaySwitch = ParamToggle( "Display Prime-ZigZag ", "No|Yes", 0 );
pZZ_PeakTrough_Shapes_DisplaySwitch = ParamToggle( "Display pZZ's PeakTrough-Shapes", "No|Yes", 0 );
pPivot_Labels_DisplaySwitch = ParamToggle( "Display pPivot-Labels", "No|Yes", 0 );
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_SECTION_BEGIN( "Define nNeo-Fractals" );
nRightside_NeoFractal_Strength = Param( "Base-Zigzag's Neo-Fractal Strength", 1, 1, 50, 1 );
nLeftside_NeoFractal_Strength = nRightside_NeoFractal_Strength; // Param( "nLeftside Neo-Fractal-Strength", 1, 0, 50, 1 );
nNeoFractal_Strength_Factor = Param( "Base-Zigzag Neo-Fractal Strength-Factor", 1, 1, 20, 1 );
nRsNFS = nRightside_NeoFractal_Strength;
nLsNFs = nLeftside_NeoFractal_Strength;
nNFSF = nNeoFractal_Strength_Factor;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Neo_HighsideInBar = PaH == Ref( PaH, -1 ) AND PaL >= Ref( PaL, -1 );
Neo_LowersideInBar = PaL == Ref( PaL, -1 ) AND PaH <= Ref( PaH, -1 );
Neo_InBar = Neo_HighsideInBar OR Neo_LowersideInBar;
nscPaH = Nz( SparseCompress( !Neo_InBar, PaH ) );
nscPaL = Nz( SparseCompress( !Neo_InBar, PaL ) );
nscIdx = Nz( SparseCompress( !Neo_InBar, Bi ) );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//nscUp_NeoFractal = nscPaH > Ref( nscPaH, -1 ) AND nscPaH >= Ref( nscPaH, 1 );
//nscDown_NeoFractal = nscPaL < Ref( nscPaL, -1 ) AND nscPaL <= Ref( nscPaL, 1 );
iLsNFS = iRsNFS = iNFSF = iPaH = iPaL = iUp_NeoFractal = iDown_NeoFractal = 0;
// This function is taken from one of online codes from Mr. @empottasch ( Edward Pottasch )
// Modified it as per my need
function Calculate_Main_Pivots( iLsNFS, iRsNFS, iNFSF, iPaH, iPaL )
{
iUp_NeoFractal = iPaH > Ref( HHV( iPaH, iLsNFS * iNFSF ), -1 ) AND iPaH >= Ref( HHV( iPaH, iRsNFS * iNFSF ), iRsNFS * iNFSF );
iDown_NeoFractal = iPaL < Ref( LLV( iPaL, iLsNFS * iNFSF ), -1 ) AND iPaL <= Ref( LLV( iPaL, iRsNFS * iNFSF ), iRsNFS * iNFSF );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Calculate_Main_Pivots( nLsNFs, nRsNFS, nNFSF, nscPaH, nscPaL );
nscUp_NeoFractal = iUp_NeoFractal;
nscDown_NeoFractal = iDown_NeoFractal;
nUp_NeoFractal = Nz( SparseExpand( !Neo_InBar, nscUp_NeoFractal ) );
nDown_NeoFractal = Nz( SparseExpand( !Neo_InBar, nscDown_NeoFractal ) );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nPeak = nUp_NeoFractal;
nTrough = nDown_NeoFractal;
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// This loop is taken from one of online codes from Mr. @empottasch ( Edward Pottasch )
_SECTION_BEGIN( "Clean nPeak-Trough" );
// 'clean' the pivots function
// meaning make the pivots alternate like Peak-Trough-Peak-Trough-Peak-Trough-etc..
xnPeak = xnTrough = 0;
function Alternate_PeakTrough( xnPeak, xnTrough )
{
global xnPeak_g;
global xnTrough_g;
// alternate pivots
xnPeak_g = xnPeak;
xnTrough_g = xnTrough;
xnPeakHigh = 0;
xnPeakHighIndex = 0;
xnTroughLow = 1e10;
xnTroughLowIndex = 0;
for( i = 0; i < BarCount - 1; i++ )
{
// consecutive lower trough found
if( xnTrough[i] AND L[i] <= xnTroughLow )
{
// disable the previous higher trough
xnTrough_g[xnTroughLowIndex] = 0;
// update trough variables
xnTroughLow = L[i];
xnTroughLowIndex = i;
// reset peak variables
xnPeakHigh = 0;
xnPeakHighIndex = 0;
}
else
// consecutive higher trough found
if( xnTrough[i] AND L[i] > xnTroughLow )
{
// disable this trough
xnTrough_g[i] = 0;
// reset peak variables
xnPeakHigh = 0;
xnPeakHighIndex = 0;
}
else
// consecutive higher peak found
if( xnPeak[i] AND H[i] >= xnPeakHigh )
{
// disable the previous lower peak
xnPeak_g[xnPeakHighIndex] = 0;
// update new peak variables
xnPeakHigh = H[i];
xnPeakHighIndex = i;
// reset trough variables
xnTroughLow = 1e10;
xnTroughLowIndex = 0;
}
else
// consecutive lower peak found
if( xnPeak[i] AND H[i] < xnPeakHigh )
{
// disable this peak
xnPeak_g[i] = 0;
// reset trough variables
xnTroughLow = 1e10;
xnTroughLowIndex = 0;
}
}
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// run clean pivots
Alternate_PeakTrough( nPeak, nTrough );
nPeak = xnPeak_g;
nTrough = xnTrough_g;
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// This code is contributed by Mr. @JohnHT ( John Stone )
_SECTION_BEGIN( "Find Missed nPeak-nTrough" );
// Find Missed Peak
nTrough_Bars = BarsSince( nTrough );
nHH_Bars = HHVBars( High, nTrough_Bars ); // Bars back to higher high since nTrough (if > 0, it is bars back to missed Peak)
nHH_Bars_Peak = IIf( nPeak, nHH_Bars, 0 ); // Restrict to current Peak bar
nHH_Bars_Peak_Reverse = Reverse( nHH_Bars_Peak ); // Can't change past so reverse time
nHH_Bars_Peak_Bars_Reverse = ValueWhen( nHH_Bars_Peak_Reverse, nHH_Bars_Peak_Reverse ); // Hold 'bars back to new Peak' forward in reversed time
nPeak_Bar_New_Reverse = Ref( nHH_Bars_Peak_Reverse, -nHH_Bars_Peak_Bars_Reverse ) == nHH_Bars_Peak_Bars_Reverse; // Find new Peak bar in reversed time
nPeak_Bar_New = Reverse( nPeak_Bar_New_Reverse ); // Restore time direction
nPeak = ( nPeak OR nPeak_Bar_New ) AND NOT nHH_Bars_Peak; // Add new Peak signal and remove old
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Find Missed Trough
nPeak_Bars = BarsSince( nPeak );
nLL_Bars = LLVBars( Low, nPeak_Bars ); // Bars back to lower low since nPeak (if > 0, it is bars back to missed Trough)
nLL_Bars_Trough = IIf( nTrough, nLL_Bars, 0 ); // Restrict to current Trough bar
nLL_Bars_Trough_Reverse = Reverse( nLL_Bars_Trough ); // Can't change past so reverse time
nLL_Bars_Trough_Bars_Reverse = ValueWhen( nLL_Bars_Trough_Reverse, nLL_Bars_Trough_Reverse ); // Hold 'bars back to new Trough' forward in reversed time
nTrough_Bar_New_Reverse = Ref( nLL_Bars_Trough_Reverse, -nLL_Bars_Trough_Bars_Reverse ) == nLL_Bars_Trough_Bars_Reverse; // Find new Trough bar in reversed time
nTrough_Bar_New = Reverse( nTrough_Bar_New_Reverse ); // Restore time direction
nTrough = ( nTrough OR nTrough_Bar_New ) AND NOT nLL_Bars_Trough; // Add new Trough signal and remove old
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_SECTION_BEGIN( "Again Clean nPeak-nTrough" );
ynPeak = ynTrough = 0;
// run clean pivots
Alternate_PeakTrough( nPeak, nTrough );
nPeak = xnPeak_g;
nTrough = xnTrough_g;
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// This loop is taken from one of online codes from Mr. @empottasch ( Edward Pottasch )
_SECTION_BEGIN( "nPivots-Camparision" );
for( i = 0; i < 3; i++ )
{
VarSet( "nPeak_x" + i, ValueWhen( nPeak, Bi, i ) );
VarSet( "nTrough_x" + i, ValueWhen( nTrough, Bi, i ) );
VarSet( "nPeakHigh_" + i, ValueWhen( nPeak, PaH, i ) );
VarSet( "nTroughLow_" + i, ValueWhen( nTrough, PaL, i ) );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nLowerLow = nTrough AND nTroughLow_1 < nTroughLow_2; // LL = LowerLow
nHigherLow = nTrough AND nTroughLow_1 > nTroughLow_2; // HL = HigherLow
nHigherHigh = nPeak AND nPeakHigh_1 > nPeakHigh_2; // HH = HigherHigh
nLowerHigh = nPeak AND nPeakHigh_1 < nPeakHigh_2; // LH = LowerHigh
nDoubleTop = nPeak AND nPeakHigh_1 == nPeakHigh_2; // DT = DoubleTop
nDoubleBottom = nTrough AND nTroughLow_1 == nTroughLow_2; // DB = DoubleBottom
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nPeakBar_01 = ValueWhen( nPeak, Bi, 1 );
nPeakBar_02 = ValueWhen( nPeak, Bi, 2 );
nPeakBar_03 = ValueWhen( nPeak, Bi, 3 );
nTroughBar_01 = ValueWhen( nTrough, Bi, 1 );
nTroughBar_02 = ValueWhen( nTrough, Bi, 2 );
nTroughBar_03 = ValueWhen( nTrough, Bi, 3 );
nPeakBarHigh_01 = ValueWhen( nPeak, PaH, 1 );
nPeakBarHigh_02 = ValueWhen( nPeak, PaH, 2 );
nPeakBarHigh_03 = ValueWhen( nPeak, PaH, 3 );
nTroughBarLow_01 = ValueWhen( nTrough, PaL, 1 );
nTroughBarLow_02 = ValueWhen( nTrough, PaL, 2 );
nTroughBarLow_03 = ValueWhen( nTrough, PaL, 3 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nLast_Pivot_Peak = nPeakBar_01 > nTroughBar_01;
nLast_Pivot_Trough = nTroughBar_01 > nPeakBar_01;
nRecent_Pivot_Peak = nPeakBar_02 > nTroughBar_02 AND nTroughBar_01 > nPeakBar_02;
nRecent_Pivot_Trough = nTroughBar_02 > nPeakBar_02 AND nPeakBar_01 > nTroughBar_02;
nPrevious_Pivot_Peak = nPeakBar_02 < nTroughBar_02 AND nTroughBar_02 < nPeakBar_01 AND nPeakBar_01 < nTroughBar_01;
nPrevious_Pivot_Trough = nTroughBar_02 < nPeakBar_02 AND nPeakBar_02 < nTroughBar_01 AND nTroughBar_01 < nPeakBar_01;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nPeakTrough_SameBar_01 = nPeakBar_01 == nTroughBar_01;
nPeakTrough_SameBar_02 = nPeakBar_02 == nTroughBar_02;
nPeakTrough_SameBar_03 = nPeakBar_02 == nTroughBar_01 AND nPeakBar_03 > nTroughBar_02;
nPeakTrough_SameBar_04 = nTroughBar_02 == nPeakBar_01 AND nTroughBar_03 > nPeakBar_02;
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// This code is taken from one of online codes from Mr. @empottasch ( Edward Pottasch )
_SECTION_BEGIN( "nZigZag Pivot's Lables" );
//nPivot_Labels_DisplaySwitch = ParamToggle( "Display nPivot-Labels", "No|Yes", 1 );
nPivot_Labels_Zorder = Param( "nPivot-Label's Zorder", 5, -5, 5, 1 );
nPivot_Label_Background_Color = ParamColor( "nLabel's Background-Color", colorBlack );
nPivot_Upper_Label_Color = ParamColor( "nUpper-Label Color", colorYellow );
nPivot_Lower_Label_Color = ParamColor( "nLower-Lable Color", colorCustom11 );
nPivot_Upper_Label_vPosition = Param( "nUpper-Label's Vertical-Position", 30, 0, 100, 1 );
nPivot_Lower_Label_vPosition = Param( "nLower-Label's Vertical-Position", -30, 0, -100, 1 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( nPivot_Labels_DisplaySwitch == 1 )
{
GfxSetZOrder( nPivot_Labels_Zorder );
for( i = 0; i < BarCount - 1; i++ )
{
if( nLowerLow[i] )
{
nString = "LL";
PlotTextSetFont( nString, Font_Name, Text_Size, i, Low[i], nPivot_Lower_Label_Color, nPivot_Label_Background_Color, nPivot_Lower_Label_vPosition );
}
if( nHigherLow [i] )
{
nString = "HL";
PlotTextSetFont( nString, Font_Name, Text_Size, i, Low[i], nPivot_Lower_Label_Color, nPivot_Label_Background_Color, nPivot_Lower_Label_vPosition );
}
if( nHigherHigh[i] )
{
nString = "HH";
PlotTextSetFont( nString, Font_Name, Text_Size, i, High[i], nPivot_Upper_Label_Color, nPivot_Label_Background_Color, nPivot_Upper_Label_vPosition );
}
if( nLowerHigh[i] )
{
nString = "LH";
PlotTextSetFont( nString, Font_Name, Text_Size, i, High[i], nPivot_Upper_Label_Color, nPivot_Label_Background_Color, nPivot_Upper_Label_vPosition );
}
if( nDoubleTop[i] )
{
nString = "DT";
PlotTextSetFont( nString, Font_Name, Text_Size, i, High[i], nPivot_Upper_Label_Color, nPivot_Label_Background_Color, nPivot_Upper_Label_vPosition );
}
if( nDoubleBottom[i] )
{
nString = "DB";
PlotTextSetFont( nString, Font_Name, Text_Size, i, Low[i], nPivot_Lower_Label_Color, nPivot_Label_Background_Color, nPivot_Lower_Label_vPosition );
}
}
}
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Except the Gfx code the rest of the code taken from one of online codes from Mr. @empottasch ( Edward Pottasch )
_SECTION_BEGIN( "Base-ZigZag" );
// nZigZag_DisplaySwitch = ParamToggle( "Display nZigZag ", "No|Yes", 1 );
// nZZ_SwingStart_Shapes_DisplaySwitch = ParamToggle( "Display ZZ's SwingStart-Shapes", "No|Yes", 0 );
// nZZ_PeakTrough_Shapes_DisplaySwitch = ParamToggle( "Display ZZ's PeakTrough-Shapes ", "No|Yes", 0 );
// nZZ_Trail_Line_DisplaySwitch = ParamToggle( "Display ZZ's Trail-Line ", "No|Yes", 0 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nZZ_Line_Zorder = Param( "nZZ Line-Zorder", 4, -5, 5, 1 );
nZZ_Line_Width = Param( "nZZ Line-Width", 2, 1, 5, 1 );
nZZ_Line_Style = ParamStyle( "nZZ Line-Style", styleLine | styleNoRescale | styleNoLabel );
nGFX_Line_Style = Param( "nGFX Line-Style", 0, 0, 5, 1 ); // Solid=0, Dash=1, Dot=2, Null=5 (Invisible-Pen).
nZZ_UpLine_Color = ParamColor( "nZZ's UpLine-Color", colorTurquoise );
nZZ_DownLine_Color = ParamColor( "nZZ DownLine-Color", colorTurquoise );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nZZ_Peak_Shape_Color = ParamColor( "nZZ Peak Shape-Color", colorCustom12 );
nZZ_Trough_Shape_Color = ParamColor( "nZZ Trough Shape-Color", colorYellow );
nZZ_Peak_Shape_Type = Param( "nZZ Peak Shape-Type", 13, 0, 50, 1 );
nZZ_Trough_Shape_Type = Param( "nZZ Trough Shape-Type", 13, 0, 50, 1 );
nZZ_Peak_Shape_vPosition = Param( "nZZ Peak-Shape's Vertical-Position", 10, 0, 100, 1 );
nZZ_Trough_Shape_vPosition = Param( "nZZ Trough-Shape's Vertical-Position", -10, 0, -100, 1 );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
iaPeak = iaTrough = 0;
iaZigZag = Null;
function Calculate_ZigZag( iaPeak, iaTrough )
{
// create ZigZag array Line
ZZ_Up = Flip( iaTrough, iaPeak );
ZZ_UpLow = ValueWhen( iaTrough, PaL, 1 );
ZZ_UpHigh = ValueWhen( iaPeak, PaH, 0 );
ZZ_UpLowIdx = ValueWhen( iaTrough, Bi, 1 );
ZZ_UpHighIdx = ValueWhen( iaPeak, Bi, 0 );
ZZ_SlopeUp = IIf( ZZ_Up, ( ZZ_UpHigh - ZZ_UpLow ) / ( ZZ_UpHighIdx - ZZ_UpLowIdx ) , Null );
ZZ_UpLine = IIf( ZZ_Up, ZZ_UpLow + ZZ_SlopeUp * BarsSince( iaTrough ), Null );
ZZ_Down = Flip( iaPeak, iaTrough );
ZZ_DownLow = ValueWhen( iaTrough, PaL, 0 );
ZZ_DownHigh = ValueWhen( iaPeak, PaH, 1 );
ZZ_DownLowIdx = ValueWhen( iaTrough, Bi, 0 );
ZZ_DownHighIdx = ValueWhen( iaPeak, Bi, 1 );
ZZ_SlopeDown = IIf( ZZ_Down, ( ZZ_DownLow - ZZ_DownHigh ) / ( ZZ_DownLowIdx - ZZ_DownHighIdx ) , Null );
ZZ_DownLine = IIf( ZZ_Down, ZZ_DownHigh + ZZ_SlopeDown * BarsSince( iaPeak ), Null );
ZigZag = IIf( ZZ_Up, ZZ_UpLine, IIf( ZZ_Down, ZZ_DownLine, Null ) );
ZigZag = IIf( Bi > Max( LastValue( ValueWhen( iaTrough, Bi ) ), LastValue( ValueWhen( iaPeak, Bi ) ) ), Null, ZigZag );
return ZigZag;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
function Calculate_LastSegment( iaPeak, iaTrough, iaZigZag )
{
Line1 = Null;
Last_PeakIdx = LastValue( ValueWhen( iaPeak, Bi ) );
Last_TroughIdx = LastValue( ValueWhen( iaTrough, Bi ) );
Last_PeakValue = LastValue( ValueWhen( iaPeak, PaH ) );
Last_TroughValue = LastValue( ValueWhen( iaTrough, PaL ) );
PeakValue = LastValue( HighestSince( Ref( iaTrough, -1 ), PaH , 1 ) );
PeakIdx = LastValue( ValueWhen( PaH == PeakValue, Bi ) );
TroughValue = LastValue( LowestSince( Ref( iaPeak, -1 ), PaL, 1 ) );
TroughIdx = LastValue( ValueWhen( PaL == TroughValue, Bi ) );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Last leg
if( Last_PeakIdx > Last_TroughIdx )
{
x0 = Last_PeakIdx;
y0 = Last_PeakValue;
x1 = TroughIdx;
y1 = TroughValue;
Line1 = LineDown = LineArray( x0, y0, x1, y1 );
iaTrough[TroughIdx] = 1;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( Last_PeakIdx < Last_TroughIdx )
{
x0 = Last_TroughIdx;
y0 = Last_TroughValue;
x1 = PeakIdx;
y1 = PeakValue;
Line1 = LineUp = LineArray( x0, y0, x1, y1 );
iaPeak[PeakIdx] = 1;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
iaZigZag = IIf( !IsEmpty( Line1 ), Line1, iaZigZag );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
function Draw_UpLine( nGfxCoordsMode, nLine_Zorder, nUpLine_Color, nLine_Width, nLine_Style, nTroughBar_01, nTroughBarLow_01, nPeakBar_01, nPeakBarHigh_01 )
{
GfxSetCoordsMode( nGfxCoordsMode );
GfxSetZOrder( nLine_Zorder );
GfxSelectPen( nUpLine_Color, nLine_Width, nLine_Style );
GfxMoveTo( nTroughBar_01, nTroughBarLow_01 );
GfxLineTo( nPeakBar_01, nPeakBarHigh_01 );
}
function Draw_DownLine( nGfxCoordsMode, nDownLine_Color, nLine_Zorder, nLine_Width, nLine_Style, nPeakBar_01, nPeakBarHigh_01, nTroughBar_01, nTroughBarLow_01 )
{
GfxSetCoordsMode( nGfxCoordsMode );
GfxSetZOrder( nLine_Zorder );
GfxSelectPen( nDownLine_Color, nLine_Width, nLine_Style );
GfxMoveTo( nPeakBar_01, nPeakBarHigh_01 );
GfxLineTo( nTroughBar_01, nTroughBarLow_01 );
}
function Draw_UpLine_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nTroughBar_02, nTroughBarLow_02, nPeakBar_01, nPeakBarHigh_01 )
{
GfxSetCoordsMode( nGfxCoordsMode );
GfxSetZOrder( nLine_Zorder );
GfxSelectPen( nLine_Color, nLine_Width, nLine_Style );
GfxMoveTo( nTroughBar_02, nTroughBarLow_02 );
GfxLineTo( nPeakBar_01, nPeakBarHigh_01 );
}
function Draw_DownLine_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nPeakBar_02, nPeakBarHigh_02, nTroughBar_01, nTroughBarLow_01 )
{
GfxSetCoordsMode( nGfxCoordsMode );
GfxSetZOrder( nLine_Zorder );
GfxSelectPen( nLine_Color, nLine_Width, nLine_Style );
GfxMoveTo( nPeakBar_02, nPeakBarHigh_02 );
GfxLineTo( nTroughBar_01, nTroughBarLow_01 );
}
function Draw_Line_PT_SameBar_to_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nTroughBar_02, nTroughBarLow_02, nPeakBar_01, nPeakBarHigh_01 )
{
GfxSetCoordsMode( nGfxCoordsMode );
GfxSetZOrder( nLine_Zorder );
GfxSelectPen( nLine_Color, nLine_Width, nLine_Style );
GfxMoveTo( nTroughBar_02, nTroughBarLow_02 );
GfxLineTo( nPeakBar_01, nPeakBarHigh_01 );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( nZigZag_DisplaySwitch == 1 )
{
nGfxCoordsMode = 1;
nLine_Zorder = nZZ_Line_Zorder;
nLine_Color = nZZ_UpLine_Color;
nUpLine_Color = nZZ_UpLine_Color;
nDownLine_Color = nZZ_DownLine_Color;
nLine_Width = nZZ_Line_Width;
nLine_Style = nGFX_Line_Style;
for( i = 0; i < BarCount - 1; i++ )
{
if( nPeakTrough_SameBar_01[i] )
{
Draw_UpLine( nGfxCoordsMode, nLine_Zorder, nUpLine_Color, nLine_Width, nLine_Style, nTroughBar_01[i], nTroughBarLow_01[i], nPeakBar_01[i], nPeakBarHigh_01[i] );
}
if( nPeakTrough_SameBar_03[i] )
{
Draw_UpLine( nGfxCoordsMode, nLine_Zorder, nUpLine_Color, nLine_Width, nLine_Style, nTroughBar_01[i], nTroughBarLow_01[i], nPeakBar_01[i], nPeakBarHigh_01[i] );
}
if( nPeakTrough_SameBar_04[i] )
{
Draw_DownLine( nGfxCoordsMode, nDownLine_Color, nLine_Zorder, nLine_Width, nLine_Style, nPeakBar_01[i], nPeakBarHigh_01[i], nTroughBar_01[i], nTroughBarLow_01[i] );
}
if( nPeakTrough_SameBar_01[i] AND nRecent_Pivot_Trough[i] )
{
Draw_UpLine_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nTroughBar_02[i], nTroughBarLow_02[i], nPeakBar_01[i], nPeakBarHigh_01[i] );
}
if( nPeakTrough_SameBar_01[i] AND nRecent_Pivot_Peak[i] )
{
Draw_DownLine_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nPeakBar_02[i], nPeakBarHigh_02[i], nTroughBar_01[i], nTroughBarLow_01[i] );
}
if( nPeakTrough_SameBar_01[i] AND nPeakTrough_SameBar_02[i] )
{
Draw_Line_PT_SameBar_to_PT_SameBar( nGfxCoordsMode, nLine_Zorder, nLine_Color, nLine_Width, nLine_Style, nTroughBar_02[i], nTroughBarLow_02[i], nPeakBar_01[i], nPeakBarHigh_01[i] );
}
}
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
nZigZag = Calculate_ZigZag( nPeak, nTrough );
Calculate_LastSegment( nPeak, nTrough, nZigZag );
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( nZigZag_DisplaySwitch == 1 )
{
nZZ_Line_Color = IIf( nZigZag, nZZ_UpLine_Color, IIf( nZigZag, nZZ_DownLine_Color, Null ) );
Plot( nZigZag, "", nZZ_Line_Color, nZZ_Line_Style, Null, Null, 0, nZZ_Line_Zorder, nZZ_Line_Width );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if( nZZ_PeakTrough_Shapes_DisplaySwitch )
{
PlotShapes( nZZ_Peak_Shape_Type * nPeak, nZZ_Peak_Shape_Color, 0, High, nZZ_Peak_Shape_vPosition );
PlotShapes( nZZ_Trough_Shape_Type * nTrough, nZZ_Trough_Shape_Color, 0, Low, nZZ_Trough_Shape_vPosition );
}
_SECTION_END();
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx