Adding Help-Tips to your programs

If you write AmiBroker programs that are used by others you have undoubtedly found that documenting your program and answering hundreds of emails can be very time consuming. You can save yourself, and those who use your code, a lot of time by adding Help popups (Tips) to your programs. No longer will users have to search though manuals and/or write emails to find basic instructions. Of course you will save time as well since you don’t have to answer all those emails :-) If you don’t program for others, read on, because there are some other applications that may interest you.

When Tips are enabled they will display as a balloon when hovering the cursor over a defined object or area, no clicks are required. Here is a typical Tip:

Tips can be used with gfx Control panels, trading dashboards, charts (function like the interpretation screen and now defunct ToolTip), tabular data, system status displays, gfx menus, caution and alert messages, etc. Your imagination sets the limits. Of course you can change the balloon size, colors, fonts, shape, etc. to your requirements. The code for the trading buttons shown is not provided in this post – that could be another topic.

Tips can display real-time market and system information. In the above example the Last price and a cautionary warning that Transmit is turned ON reflect real-time status.

In this post Tips are placed relative to the mouse’s cursor position. In chart applications you might want to use dynamically placed Tips that point to a critical event or condition on your chart. You would do this by converting price and bars to pixels and replace the MX and MY variables in the code with calculated values. For more on this see How to convert from bar-value to pixel coordinates on the AmiBroker Knowledge Base.

When I write button functions I add Tip information as the last argument to the function, this way the information is right where it is defined by the code. This is also helpful when reading the code. The actual Tip text can be repeated in your manual as a text box so that a clear association exists.

The code in this post demonstrates how the balloon reorients itself depending on in which quadrant of the pane the cursor is located. This is done to keep tips within the pane area, even when hovering over an object close to the edge of the pane. Here is a short video to see how this works.

If, on your computer, the Tip tracks the mouse cursor slower than in the video this is because I have enabled the higher refresh rate of 0.1 second. Tomasz explained this in post 151255 on the main AmiBroker list. Making errors while editing your Registry can cause serious computer problems, if you haven’t done this before, please seek professional help.

All code in this post is solely intended to show you how to develop Tips. They serve no other purpose. To help you experiment I used Param() instead of hard-coding Tip properties:

Have fun!


function ShowTipTipColorTipOutlineColorTipTextColor )
{
global MXMYPxWidthPxHeightTipWidthTipHeightTipsOnTipFontNameTipFontSize;
TipMsg VarGetText"TipMsg" );

if ( TipsOn AND TipMsg != "" )
{
Quadrant = ( MX &ltpxwidth ) + ( MY &ltpxheight ) * 2;
D  30// Rounding Diameter

switch ( Quadrant )
{

case 3:
X1 MX;
Y1 MY 0.75;
X2 MX TipWidth;
Y2 MY TipHeight 0.75;
X3 MX 0.75;
Y3 Y1;
X4 MX 2;
Y4 Y1;
X5 MX;
Y5 MY;
break;

case 2:
X1 MX TipWidth;
Y1 MY 0.75;
X2 MX;
Y2 MY TipHeight 0.75;
X3 MX 0.75;
Y3 Y1;
X4 MX 2;
Y4 Y1;
X5 MX;
Y5 MY;
break;

case 1:
X1 MX;
Y1 MY TipHeight 0.75;
X2 X1 TipWidth;
Y2 Y1 TipHeight;
X3 MX D;
Y3 Y2 1;
X4 MX 0.75;
Y4 Y2 1;
X5 MX;
Y5 y2 0.75;
break;

case 0:
X1 MX TipWidth;
Y1 MY TipHeight 0.75// Rectangle
X2 X1 TipWidth;
Y2 Y1 TipHeight;
X3 X2 D;
Y3 Y2 1// Pointer
X4 X2 0.75;
Y4 Y2 1;
X5 X2;
Y5 y2 0.75;
break;

default:
x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 0;
}

GfxSetBkMode);

GfxSelectPenTipOutlineColor );
GfxSetTextColorTipTextColor );
GfxSelectFontTipFontnameTipFontSize );
GfxSelectSolidBrushTipColor );
GfxRoundRectX1y1x2y2D);
GfxPolygon(   X3Y3 X4 Y4X5Y5 );     // Pointer
GfxSelectPenTipColor ); // Hide line between RoundRect and Pointer
GfxMoveToX3Y3 );
GfxLineToX4Y4 );
GfxDrawTextTipMsgx1 10y1 3x2 10y2 516 65 );
}
}

function TestObjectLabelX1Y1X2Y2Color // Do-Nothing Demo function only
{
GfxSelectPencolorBlack );
GfxSelectSolidBrushColor );
GfxRectangleX1y1x2y2 );
OverObject MX &gtx1 AND MX &ltx2 AND MY &gty1 AND MY &lty2;

if ( OverObject )
VarSetText"TipMsg""The cursor is now over the " Label +
" quadrant and the shape of the Tip is adjusted accordingly." );

return OverObject;
}

// Global variables and parameters can be hard-coded in the final application
global MXMYPxWidthPxHeightTipWidthTipHeightTipsOnFontNameFontSize;
TipColor          ParamColor"Tip Background Color"colorWhite );
TipOutlineColor ParamColor"Tip Outline Color"colorBlack );
TipTextColor   ParamColor"Tip Text Color"colorBlack );
TipsOn             ParamToggle"Tips On""OFF|ON");
TipFontSize    Param"Font Size"9024);
TipWidth          Param"Tip Width"2205050010 );
TipHeight         Param"Tip Height"805050010 );
TipFontName       ParamStr"Tip Font name""Lucida Console" );

GfxSetBkMode);
GfxSetOverlayMode);
RequestTimedRefresh0.1 );
MX         GetCursorXPosition);
MY         GetCursorYPosition);
PxWidth    Status"pxwidth" );
PxHeight    Status"pxheight" );

// In a real application each colored area could be s small button
TestObject"UpperLeft"00pxwidth 2pxheight 2colorRed );
TestObject"UpperRight"pxwidth 20pxwidthpxheight 2colorBlue );
TestObject"LowerLeft"0pxheight 2pxwidth 2pxheightcolorYellow );
TestObject"Lowerright"pxwidth 2pxheight 2pxwidthpxheightcolorBrightGreen );

ShowTipTipColorTipOutlineColorTipTextColor ); // Place this call at the very endo of your code

Reducing Indicator-Lag

The usual way to reduce Indicator lag in averaging formulas, such as the MA(), EMA, and Tilson T3(), is to try and dream up a completely new formula. This isn’t easy. It is often easier to remove lag from an already smoothed plot, than to improve the basic smoothing formula.

Indicator Delay is often an essential Indicator quality and (imo) is not the same as Indicator Lag. The ideal smoothing function is one with zero delay, i.e., one that tracks the price with a perfectly smooth-looking plot. Delay can be added later as an independent quality using the ref() function. Some smoothing formulas already have a sensitivity adjustment, these will not necessarily behave in the same manner as the LagReducing factor used below. Optimizing all parameters for best results is recommended.

The Lag-Reducing formula presented here can be applied to most averaging formulas and to indicators that are based on averages (like Bands). The lag reducing parameter (RLFactor) of the Reducelag() function can also be used to make formulas adaptive with respect to another price or Indicator quality. The image below shows how lag has been reduced for the Tilson T3 formula.

To see how this formula works Apply the code show below to a new indicator pane, open the Parameter window, and try  different settings.

function T3PriceT3Periods)
{
    e1    AMAPrice/ ( T3Periods ) );
    e2    AMAe1/ ( T3Periods ) );
    e3    AMAe2/ ( T3Periods ) );
    e4    AMAe3/ ( T3Periods ) );
    e5    AMAe4/ ( T3Periods ) );
    e6    AMAe5/ ( T3Periods ) );
    C1 = -3;
    C2 * ( );
    C3 = -* ( ) ^ 2;
    C4 = ( ) ^ 3;
    T3Result c1 e6 c2 e5 c3 e4 c4 e3;
    return NzT3Result );
}

function ReduceLagIndicatorRLFactor )
{
    return ( Indicator RefIndicator, -) ) ^ RLFactor*Indicator;
}

_SECTION_BEGIN"REDUCING INDICATOR LAG" );
LRFactor         Param"Lag-Reducing Factor"1.70100.1 );
Periods         Param"T3 Periods"5110);
Sensitivity        Param"T3 Sensitivity 1"0.7030.03 );

I1 T3OPeriodsSensitivity );
I2 ReducelagI1LRFactor );

PlotC"Close"1128 );
PlotI1"\nBasic T3"2);
PlotI2"\nLag-Reduced T3"4styleNoRescale );
_SECTION_END();