Amibroker Canada User Group
November 5th, 2019
Adding Ribbons to Charts
A story about how I solved a massive number of charts problem.
Wayne Yeo - swyeo@[Link]
Breadth measures are copyright Riverside Analytics Inc
I had a need for
• Absorbing a large volume of data
• Understanding complex data quickly
• Multiple technicals in one view
• Easy understanding of Interrelationships
between data
• Tracking changes over time
Why did I do this ?
• Request from company *
• create breadth charts
• one chart per sector
• Original idea - 4 panes per chart in Amibroker
• All US sectors, plus
• All Canadian Sectors, added later
• All US industries – 100 +
• Pain to manage
* Some Details are proprietary, Riverside Analytics Inc
TSX Composite Market Breadth - Example of where I started
Advance Decline, High Low Percent, Percent Above x 3, Cumulative P x V
Lots of information
Difficult to consume
Remember each market sector
Needed easier solution
Heading for 150 + Charts !
Typical example of new chart - SP1500 - US - VTI - 500 LgCap, 400 Midcap, 600 Smallcap
Breadth – Percent Above MA - 3 versions, New High Low – 3 versions, High Low Percent,
and Advance Decline Percent
• Price colour based
on Trend Filter
11 Ribbons
• Force
• Stochastic
• Trend Filter
• 8 Breadth
Excluding F, S & TF
Green test
5 or > Bullish Breadth
3 or < Bearish Breadth
• Need a fast way to process each chart
• Build menu system !
• No more multi tab Amibroker screens !
Note colour
gradations
Of the
Stochastic
Ribbon
Lots of information
Much easier to consume
This has 2 sisters,
US industry, TSX Sectors
Canadian Industry Change Request
Produce 150 + Charts in a couple hours
Some hints on how I did it.
What does the ribbon code look like?
A bit of setup code first
// menu item selector
DisplayWhichBreadth = ParamList("Display Which Breadth ?",
"TSX|SP1500|SP500|SP400|SP600|NDAQ100|US_DOW|US_BANKS|US_BIOTK|US_CD|US_CS|US_DIV|US_E
N|US_FIN|US_HC|US_IND|US_MAT|US_MTLS|US_PHARMA|US_RE|US_REIT|US_TECH|US_TLCM|US_UTL"
);
RibbonThickness = Param("Ribbon Thickness", 1.25, 1, 5, 0.1);
Font = ParamList("Font:","Arial|Calibri|Futura|Tahoma|Times New Roman");
RibbonNumber = 9; // first free ribbon number after the breadth ribbons, increment the ribbon number as
necessary
DisplayForce = ParamList("Display Force Ribbon ?", "Y|N");
What does the ribbon code look like?
Three key pieces of code -
// Ribbon Code found on the internet, adapted for Breadth Plots
// [Link]
You need to be a Amibroker member to have access to the blogging area.
First – Determine the width of the ribbon to be plotted by the MultiRibbon procedure
///////////////////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////////////////
function GfxConvertBarToPixelX(Bar)
{
lvb = Status("lastvisiblebar"); fvb = Status("firstvisiblebar");
pxchartleft = Status("pxchartleft"); pxchartwidth = Status("pxchartwidth");
return pxchartleft + Bar * pxchartwidth / (Lvb - fvb + 1);
}
What does the ribbon code look like? – Colour assignment
Second piece – (formatting is fine inside amibroker !) ONLY USED FOR THE STOCHASTIC GRADATIONS !
///////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION WHICH CALCULATES AND RETURN THE DIFFERENT SHADES OF GREEN AND RED COLORS:
///////////////////////////////////////////////////////////////////////////////////////////////////
function FillColor(Value, MaxPosVal, MinPosVal, MaxNegVal, MinNegVal)
{
UpRed = 0;
UpGreen = 255;
UpBlue = 0;
DnRed = 255;
DnGreen = 0;
DnBlue = 0;
DarkColor = 0;
LightColor = 230;
Upred = IIf(Value > 0, LightColor - int((LightColor-(((MaxPosVal-Value)*(LightColor-DarkColor))/(MaxPosVal-MinPosVal + 0.001)))),
IIf(Value== 0, 255, 0));
UpBlue = UpRed;
DnGreen = IIf(Value <= 0, LightColor - int((LightColor-(((abs(MaxNegVal)-abs(Value))*(LightColor-DarkColor))/(abs(MaxNegVal)-
abs(MinNegVal) + 0.001)))),IIf(Value == 0, 255, 0));
DnBlue = DnGreen;
Color = IIf(Value >= 0, ColorRGB(UpRed, UpGreen, UpBlue), ColorRGB(DnRed,DnGreen, DnBlue));
return Color;
}
What does the ribbon code look like?
Third piece – Plot an individual ribbon
///////////////////////////////////////////////////////////////////////////////////////////////////
// plot the bar number specified in the call
///////////////////////////////////////////////////////////////////////////////////////////////////
// parameters >> MultiRibbon("Color", "Ribbon Number", "Name To Display");
procedure MultiRibbon(RibbonColor, Position, Label)
{
LineColor = colorLightGrey;
Position = RibbonThickness * Position;
x2 = Status("pxchartright");
y2 = Status("pxchartbottom");
// leading section gets turned yellow for the label area
RibbonColor = IIf(GfxConvertBarToPixelX(BarIndex()-Status("firstvisiblebarindex")) > y2/1.5 *
(RibbonThickness/100) * 18 , RibbonColor, colorYellow);
Plot(0, "", LineColor, styleOwnScale | styleNoLabel, 0, 100);
Plot(Position, "", LineColor, styleOwnScale | styleNoLabel, 0, 100);
Plot(Position, "", RibbonColor, styleArea | styleOwnScale | styleNoLabel, 0, 100);
GfxSetTextColor(colorBlack);
GfxSelectFont(Font, y2/1.7 * (RibbonThickness/100), 400); // 2019 0204 changed 1.5 to 1.7, reduce font size a bit.
GfxDrawText(Label, 8, y2 * 1.001 -(y2 * Position/100) , y2/1.5 * (RibbonThickness/100) * 17, y2, 2 + 32 + 256);
}
What does the ribbon code look like?
Plot instruction that uses the above 3 pieces of code.
The “Color” parameter is used two ways. For the Force, and Trend Filter, I preassign the colours.
For the Stochastic, I use the FillColor function to get the gradations.
Basic form of use :
MultiRibbon("Color", "Ribbon Number", "Name To Display");
// set the colour arrays - binary decision – Red or Green
SP1500_TOTIDX_ADP_dynamic_color = IIf( C_SP1500_TOTIDX_ADP > 0, colorGreen, colorRed ); // * footnote
.
.
SP1500_TOTIDX_PctAbv200_dynamic_color = IIf( C_SP1500_TOTIDX_PctAbv200 > 0, colorGreen, colorRed ); // * footnote
// plot the ribbon – Notice I assigned the colour in this call – binary decision – Red or Green
MultiRibbon(SP1500_TOTIDX_ADP_dynamic_color , 1, "SP1500_TOTIDX_ADP ");
.
.
MultiRibbon(SP1500_TOTIDX_PctAbv200_dynamic_color , 8, "SP1500_TOTIDX_PctAbv200 ");
* Actual breadth calculations are proprietary, and copyrighted by Riverside Analytics Inc
What does the ribbon code look like? A couple extra pieces –
FORCE, Trend Filter
Each chart has its own piece of code, each chart is driven off a foreign symbol.
if (DisplayWhichBreadth == "SP1500") // User driven chart to display
{
//…. proprietary code in here
RibbonNumber = 9; // Dynamic ribbon number building
if (DisplayTF == "Y") // display the trend filter ?
{
MultiRibbon(TFCLR , RibbonNumber, " TLs TF ");
RibbonNumber = RibbonNumber + 1;
}
if (DisplayForce == "Y") // display force index ?
{
MultiRibbon(Force_Index_kolor , RibbonNumber, " Force Index ");
}
}
What does the ribbon code look like? A couple extra pieces – STOCHASTIC colour calculation
// if you are not displaying the stochastic, then do not calculate it
if (DisplayStoc == "Y")
{
//=====================================================================================================
// PREMIER STOCHASTIC OSCILLATOR WITH "AWESOME INDICATOR" COLORING CALCULATIONS:
//=====================================================================================================
StochLen = PREMIER_STOCHASTIC_Stoch_Len;
Period = PREMIER_STOCHASTIC_Period;
SK = StochK( StochLen, 1 );
Len = sqrt( Period );
NormStochK = 0.1 * ( SK - 50 );
SmoothStoch = EMA( EMA( NormStochK, Len ), Len );
expSS = exp( SmoothStoch );
Premier = ( expSS - 1 )/( expSS + 1 );
// Borrowed this from the Awesome Indicator:
SlowMA = MA( Avg ,34);
FastMA = MA( Avg,5);
// Modify the value, so we can calculate the colors using the standard function:
Value = Premier + 1;
MaxValue = 2;
MinValue = 0;
Stoch_Color = IIf((SlowMA - FastMA) <= Ref(SlowMA - FastMA, -1), FillColor(Value,
MaxValue, MinValue, 0, 0), FillColor(-Value, 0,0, -MinValue, -MaxValue));
}
Recent enhancement
Sometimes the graph interferes with the chart, give the ribbon some of its own room
GraphXSpace_Space = Param("Ribbon Space", 20, 0, 80, 5);
GraphXSpace = GraphXSpace_Space; // added 2019 1021
Forces the chart to allocate 20 percent blank pace top / bottom
Not ideal, but works
Prefer not to reduce upper chart, just lower chart
Summary
Started with a large number of charts problem
Messed about with a number of intermediate solutions
Ribbon solution embedded in the chart is very effective
Menu system makes producing Powerpoint Report easier to accomplish.
Whole thing, data download to report delivery, about 2 – 2.5 hours, it will be 3
hours once TSX industry charts are done.
Likely over 200 charts in the final product.
Riverside Analytics Inc
Among other things,
We use Breadth and Trend as two key components to help our members make
better decisions with their investments.
If you would like more information, we can be contacted at :
RiversideAnalyticsInc@[Link]
Tim Koen is principal owner.