// Method DisplayParam() requires 2X number of bars that are shown on screen to be loaded on chart. Otherwise, will not calc correctly. // May be simpler to just specific vertical value for the two labels, and input an offset for the text of each label to start. { Indicator: _RibbonsPlotter Description: This Indictor plots various types of ribbons (multiple bands of deviation functions) around a centerline reference function. Provided By: MarkSanDiego Updated: 02/18/07 original version 09/14/08 fixed offset 01/03/09 lower band function formula error correction 01/04/09 future projections added (FutureOffset = 1 or 2) 04/30/09 clean up and tighten code 05/29/09 add display of input parameters on chart 07/08/09 _BarsDisplayed function modified to minimize increase in MaxBarsBack cause by back referencing to print chart labels after LastBarOnChart reached. 07/10/09 WVAP added to centerline functions 08/15/09 _RibbonsCalc function modified. Band calculations done within this indicator rather than within _RibbonsCalc, as strategies will also use _RibbonCalc and strategies do not need calculation of ribbon arrays. 04/11/10 added capability estimate next bar value of center line based on center line rate of change and acceleration. This useful when used in conjuntion with strategies that generate orders in Buy/Sell Next Bar at [value] format. 06/02/11 Remove Jurik functions for forum posting. 07/16/11 Replace function RibbonsCalc with local Method RibbonsCalc. This avoids the added complexity of sending a large number of parameters to function RibbonsCalc. 01/01/12 offset calculation error corrected 01/01/12 replace plotting code with Method PlotRibbons() 02/26/12 include offset with JMA centerline calculation 12/08/12 Error in label positioning on chart corrected. 01/15/13 Improve labelling code. 01/16/13 Add real time intrabar re-calculations 01/28/13 Add display parameter offset 02/23/13 Modify display parameters. 08/06/13 Modifying position of display parameters to right justify against chart edge. 11/02/13 Fixed bug with linear regression centerlines not recognizing the TargetBar input parameter _____________________________________________________________________________________________________________ { Reference Function (Center line) May be: } 0-Zero axis 1-AMA (Arithmetic Average) 2-EMA (Exponential Moving Average 3-LR (Linear Regression) 4-Adaptive Moving Avg (Kaufman - KAMA) 5-T3 Triple Exponential Moving Average 6-JMA Juric Moving Average or 7-WVAP 8-Fixed Value { Deviation Function (Band or Ribbons) may be: } 1-Standard Deviation (Bollinger Bands) 2-Standard Error 3-ATR (Average True Range - Keltner Bands) 4 JMA True Range (ATR using Jurik Moving Avg) 5-Pct (Percentage) 6-Points ______________________________________________________________________________________________________________ } [LegacyColorValue = true]; Inputs: Price(close), Smooth(0), UpperBandsRef(avgprice), LowerBandsRef(avgprice), Offset(1), RefID(3), AMALength(15), { arithmetic moving average length } EMALength(15), { exponential moving average length } LRLength(300), { linear regression function length } LRTgtBar(0), { linear regression function target bar. Use negative Value1 to project into future. } KAMA_EffRatioLen(7), { Kaufman adaptive moving average parameters } KAMA_FastLength(2), { Kaufman adaptive moving average parameters } KAMA_SlowLength(25), { Kaufman adaptive moving average parameters } T3Length(20), JMALength(5), JMAPhase(0), VWAP_("No Param RefID = 7"), RefValue(0), DevID(2), { deviation function identifier } StdDevLength(0), { standard deviation length } StdErrLength(0), { standard error length } ATRLength(14), { average true range length } JATRLength(14), { percentage } Percent(1), Pts(1), NBands(5), { maximum 8 } StartMult(0.7), Increment(0.95), AddMinus(0), RoundToTradable(true), PlotWidth(0), ShowCenterLine(true), ShowCenterLineTrendColor(false), { color centerline indicating direction of trend } DisplayParameters(true), { display chart parameters } RefTextHeightPct(30), { Reference Text info vertical height % } DevTextHeightPct(20), { Deviation Text info vertical height % } DisplayParamOffset(4), { Display parameters offset } CLTextColor(yellow), { center line parameters text display color } DevTextColor(cyan), { deviation parameters text display color } RefVertPct(8), { vertical position in chart range percent for center line parameter display } DevVertPct(3), { vertical position in chart range percent for deviation parameter display } int CalcSeconds(10); Arrays: UpperBand[9](0), LowerBand[9](0); Vars: intrabarpersist UpperCL(0), intrabarpersist LowerCL(0), intrabarpersist UpperDev(0), intrabarpersist LowerDev(0), Intrabarpersist DevLength(0), n(0), x(0), { function LinearRegFaster variables } oLRSlope( 0), oLRAngle( 0), oLRIntercept(0), { left intercept, value of beginning of LR line (at offset of [ Length - 1 ] bars } oLRValueRaw(0), { _StdDevMean variables } oMean(0), { chart display parameters } Intrabarpersist BS(0), Intrabarpersist LastBar(false), Intrabarpersist Calc(false), intrabarpersist string Text1(""), intrabarpersist string Text2(""), intrabarpersist TextID1(0), intrabarpersist TextID2(0), intrabarpersist TextVertPct1(RefVertPct), { percentage of range to display Text1 } intrabarpersist TextVertPct2(DevVertPct), { percentage of range to display Text1 } intrabarpersist TextVert1(0), { vertical Value1 at which to Display Text1 } intrabarpersist TextVert2(0), { vertical Value1 at which to Display Text2 } intrabarpersist DisplayHigh(0), intrabarpersist DisplayLow(0), intrabarpersist DisplayRange(0), { vertical Range of chart } Intrabarpersist MidRange(0), { vertical middle of charting } // intrabarpersist TextLength1(0), // intrabarpersist TextLength2(0), // intrabarpersist TextLengthMax(0), { variables for method RibbonCalc } { if StdDevLength or StdErrLength = 0, then set length same as linear regression center line length (LRLength) } SDLength(MaxList(iff(StdDevLength > 2, StdDevLength, LRLength), 2)), { standard deviation requires minimum length of 2 } SELength(MaxList(iff(StdErrLength > 3, StdErrLength, LRLength), 3)); { standard error requires minimum length of 3 } var: elsystem.Timer Timer1( NULL ); Method override void InitializeComponent() begin Timer1 = new elsystem.Timer; Timer1.Interval = CalcSeconds * 1000; Timer1.AutoReset = true; Timer1.Enable = true; Timer1.Name = "Timer1"; Timer1.elapsed += Timer1_Elapsed; end; { run once every CalcSeconds seconds} Method void Timer1_Elapsed( elsystem.Object sender, elsystem.TimerElapsedEventArgs args ) begin //BS = -1; { all timer generated executions associated with BarStatus(1) = -1 (undefined) } Calc = true; end; Method void RibbonsCalc() begin { ESTABLISH CENTERLINE } switch RefID begin Case 0: UpperCL = UpperBandsRef[Offset]; case 1: UpperCL = AverageFC(UpperBandsRef[Offset], AMALength); case 2: UpperCL = _XAverage.Simple(UpperBandsRef[Offset], EMALength); case 3: Value1 = _LinearRegFaster(UpperBandsRef[Offset], LRLength, LRTgtBar, oLRSlope, oLRAngle, oLRIntercept, UpperCL ); case 4: UpperCL = _KAMA(UpperBandsRef[Offset], KAMA_EffRatioLen, KAMA_FastLength, KAMA_SlowLength); case 5: UpperCL = T3Average.Simple(UpperBandsRef[Offset], T3Length); { {comment out next 2 lines if Juric moving average not installed } case 6: UpperCL = JRC.JMA.2k(UpperBandsRef[offset], JMALength, JMAPhase); } case 7: UpperCL = _VWAP; case 8: UpperCL = RefValue; end; if LowerBandsRef = UpperBandsRef then begin LowerCL = UpperCL; end else begin switch RefID begin Case 0: LowerCL = LowerBandsRef[Offset]; case 1: LowerCL = AverageFC(LowerBandsRef[Offset], AMALength); case 2: LowerCL = _XAverage.Simple(LowerBandsRef[Offset], EMALength); case 3: Value1 = _LinearRegFaster(LowerBandsRef[Offset], LRLength, LRTgtBar, oLRSlope, oLRAngle, oLRIntercept, LowerCL ); case 4: LowerCL = _KAMA(LowerBandsRef[Offset], KAMA_EffRatioLen, KAMA_FastLength, KAMA_SlowLength); case 5: LowerCL = T3Average.Simple(LowerBandsRef[Offset], T3Length); { { comment out the next two lines if Jurik functions are not installed } case 6: LowerCL = JRC.JMA.2k(LowerBandsRef[Offset], JMALength, JMAPhase); } case 7: LowerCL = _VWAP[Offset]; case 8: LowerCL = RefValue; end; end; { ESTABLISH FUNCTION } switch DevID begin case 1: value1 = _StdDevMean(UpperBandsRef[Offset], SDLength, 1, oMean, UpperDev); Case 2: UpperDev = _StdError(UpperBandsRef[Offset], SELength); case 3: UpperDev = _AvgTrueRange(ATRLength)[Offset]; { { comment out the next two lines if Jurik functions are not installed } case 4: UpperDev = _JMATrueRange(JATRLength)[Offset]; } case 5: UpperDev = UpperBandsRef[Offset] * Percent / 100; case 6: UpperDev = Pts; end; if LowerBandsRef = UpperBandsRef then begin LowerDev = UpperDev; end else begin switch DevID begin case 1: value1 = _StdDevMean(LowerBandsRef[Offset], SDLength, 1, oMean, LowerDev); Case 2: LowerDev = _StdError(LowerBandsRef[Offset], SELength); case 3: LowerDev = UpperDev; case 4: LowerDev = UpperDev; case 5: LowerDev = LowerBandsRef[Offset] * Percent / 100; case 6: LowerDev = Pts; end; end; end; { Method RibbonCalc } Method void LoadBandsArray() begin { ROUND OFF to tradeable value } if RoundToTradable then begin { with rounding } for n = 1 to NBands begin x = StartMult + (n - 1) * Increment; UpperBand[n] = Round2Fraction(UpperCL + x * UpperDev + AddMinus); LowerBand[n] = Round2Fraction(LowerCL - x * LowerDev + AddMinus); end; UpperBand[0] = Round2Fraction(UpperCL); LowerBand[0] = Round2Fraction(LowerCL); end else begin { no rounding off } for n = 1 to NBands begin x = StartMult + (n - 1) * Increment; UpperBand[n] = UpperCL + x * UpperDev + AddMinus; LowerBand[n] = LowerCL - x * LowerDev + AddMinus; end; UpperBand[0] = UpperCL; LowerBand[0] = LowerCL; End; end; { Method LoadBandsArray } Method void InitializeTextLabels() begin { Reference function parameters } switch RefID begin Case 0: Text1 = "Center Line: " & "Zero axis"; Case 1: Text1 = "Center Line: " & "AMA " & NumToStr(AMALength, 0); Case 2: Text1 = "Center Line: " & "EMA " & NumToStr(EMALength, 1); Case 3: Text1 = "Center Line: " & "LinReg " & NumToStr(LRLength, 0) & " Offset " & NumToStr(Offset,0) & " oTgtBar " & NumToStr(LRTgtBar, 0); Case 4: Text1 = "Center Line: " & "KAMA " & NumToStr(KAMA_EffRatioLen, 1) & ", " & NumToStr(KAMA_FastLength, 1) & ", " & NumToStr(KAMA_SlowLength, 1); Case 5: Text1 = "Center Line: " & "T3 " & NumToStr(T3Length, 0); Case 6: Text1 = "Center Line: " & "JMA " & NumToStr(JMALength, 0) & " Phase " & NumToStr(JMAPhase, 0); Case 7: Text1 = "Center Line: " & "VWAP"; Case 8: Text1 = "Center Line: " & "Value = " & NumToStr(RefValue, 1); end; { switch RefID } { Deviation function parameters } switch DevID begin Case 1: { if no length specified, use length of reference function } Text2 = "Deviation: " & "Std Dev " & NumToStr(SDLength, 0) & " Mult: " & NumToStr(StartMult,1); Case 2: { if no length specified, use length of reference function } Text2 = "Deviation: " & "Std Err " & NumToStr(SELength, 0) & " Mult: " & NumToStr(StartMult,1); Case 3: Text2 = "Deviation: " & "ATR " & NumToStr(ATRLength, 0) & " Mult: " & NumToStr(StartMult,1); Case 4: Text2 = "Deviation: " & "JURIC ATR " & NumToStr(JATRLength, 0) & " Mult: " & NumToStr(StartMult,1); Case 5: Text2 = "Deviation: " & "Percent " & NumToStr(Percent, 1) & " Mult: " & NumToStr(StartMult,1); Case 6: Text2 = "Deviation: " & "Points " & NumToStr(Pts, 2) & " Mult: " & NumToStr(StartMult,1); end; { switch DevID } TextID1 = Text_New(0, 0, 0, Text1); TextID2 = Text_New(0, 0, 0, Text2); value1 = Text_SetColor(TextID1, CLTextColor); value2 = Text_SetColor(TextID2, DevTextColor); Value1 = Text_SetStyle(TextID1, 1, 2) ; { center vertically and horizontally } Value1 = Text_SetStyle(TextID2, 1, 2) ; { center vertically and horizontally } { TextLength1 = StrLen(Text1); TextLength2 = StrLen(Text2); TextLengthMax = MaxList(TextLength1, TextLength2) + DisplayParamOffset; } end; { Method InitializeTextLabels } Method void DisplayParam() begin DisplayHigh = GetAppInfo( aiHighestDispValue ) ; DisplayLow = GetAppInfo( aiLowestDispValue ) ; DisplayRange = DisplayHigh - DisplayLow; MidRange = (DisplayHigh + DisplayLow)/2; { Place label away from price action } If Close > MidRange then begin TextVert1 = DisplayLow + 0.01 * TextVertPct1 * DisplayRange; TextVert2 = DisplayLow + 0.01 * TextVertPct2 * DisplayRange; End else begin TextVert1 = DisplayHigh - 0.01 * TextVertPct2 * DisplayRange; TextVert2 = DisplayHigh - 0.01 * TextVertPct1 * DisplayRange; end; Text_SetLocation(TextID1, Date[DisplayParamOffset], Time[DisplayParamOffset], TextVert1) ; Text_SetLocation(TextID2, Date[DisplayParamOffset], Time[DisplayParamOffset], TextVert2) ; end; { Method DisplayParam } Method void PlotRibbons() begin { PLOTTING } If NBands >= 1 Then Begin Plot8(UpperBand[1],"Hi-1", default, default, PlotWidth); Plot10(LowerBand[1],"Lo-1", default, default, PlotWidth); If NBands >=2 Then Begin Plot7(UpperBand[2],"Hi-2", default, default, PlotWidth); Plot11(LowerBand[2],"Lo-2", default, default, PlotWidth); If NBands >=3 Then Begin Plot6(UpperBand[3],"Hi-3", default, default, PlotWidth); Plot12(LowerBand[3],"Lo-3", default, default, PlotWidth); If NBands >= 4 Then Begin Plot5(UpperBand[4],"Hi-4", default, default, PlotWidth); Plot13(LowerBand[4],"Lo-4", default, default, PlotWidth); If NBands >= 5 Then Begin Plot4(UpperBand[5],"Hi-5", default, default, PlotWidth); Plot14(LowerBand[5],"Lo-5", default, default, PlotWidth); If NBands >=6 Then Begin Plot3(UpperBand[6], "Hi-6", default, default, PlotWidth); Plot15(LowerBand[6],"Lo-6", default, default, PlotWidth); If NBands >=7 Then Begin Plot2(UpperBand[7],"Hi-7", default, default, PlotWidth); Plot16(LowerBand[7],"Lo-7", default, default, PlotWidth); If NBands >=8 Then Begin Plot1(UpperBand[8],"Hi-8", default, default, PlotWidth); Plot17(LowerBand[8],"Lo-8", default, default, PlotWidth); End; End; End; End; End; End; End; End; if ShowCenterLine then begin Plot9(UpperCL[0], "URef", default, default, PlotWidth); If LowerCL[0] <> UpperCL[0] Then Plot18(LowerCL[0], "LRef", default, default, PlotWidth); end; if ShowCenterLineTrendColor then begin if (UpperBand[0] - UpperBand[0][1]) >= 0 then SetPlotColor[1](9, green) else SetPlotColor[1](9, red); if LowerBand[0] <> UpperBand[0] then begin if (LowerBand[0] - LowerBand[0][1]) >= 0 then SetPlotColor[1](18, green) else SetPlotColor[1](18, red); end; end; if Smooth > 0 then Plot21(Average(Price, Smooth), "Smooth Price"); // if Smooth > 0 then Plot21(JRC.JMA.2k(Price, Smooth,0), "Smooth Price"); // may use this line if Jurik Moving Average functions are installed end; { Method PlotRibbons } #region Main Program BS = BarStatus(1); once(_LastBarOnChart) begin LastBar = true; end; Switch BS begin Case 1: #region Every Tick Processing #region Triggered Calculations { Calculate immediately at start of real time data } once Calc = true; { ReCalculate and Plot once every CalcSeconds during real time data } If Calc then begin #region Calculate Ribbons RibbonsCalc(); #endregion { load center line and deviations into arrays } #region Load Bands Array LoadBandsArray(); #endregion #region PlotRibbons PlotRibbons(); #endregion #region Display Parameter info if DisplayParameters and LastBar then begin DisplayParam(); end; #endregion Calc = false; end; #endregion; { Triggered Calculations } #endregion { Tick Processing } Case 2: #region EndOfBar Processing Once InitializeTextLabels(); #region Calculate Ribbons RibbonsCalc(); #endregion { load center line and deviations into arrays } #region Load Bands Array LoadBandsArray(); #endregion #region PlotRibbons PlotRibbons(); #endregion #endregion { EndOfBar Processing } #region LastBar Processing #region Display Parameter info if DisplayParameters and LastBar then begin DisplayParam(); end; #endregion #endregion end; #endregion { Main Program }