@mkj9090, in my opinion, the best way to handle alerts in AmiBroker is using the versatile Alertif() function.
Be sure to read Using formula-based alerts to learn more about this topic and then search the forum to be aware of potentials problems (and relative solution) experienced by other users.
However, if you still prefer the easiest way (something that can rapidly become more difficult
) below you will find an example that I have assembled to show you the use of some features that might be useful for your goal.
I tested this code on 1 minute RT feed, and it seems to work. But, since my experience with intraday code is very limited (I usually work with EOD) I will not be surprised if you'll find some issues and/or logic errors to be fixed (by you or some more experienced user that will kindly join this thread).
The (fake) Buy/Sell rules I used here are explicitly intended NOT for a real trading system, but ONLY for testing purposes since they will frequently trigger the alerts (to verify the code logic and, if anyone will ever dare to use it, to make his broker rich
).
Anyway, the main idea was to avoid a lot of popups/sounds in a short sequence, and the solution comes from the Say() function example; it uses a StaticVar to ignore redundant vocal messages. The same logic was applied to popup windows.
(If you don't like the text2speech functionality you can replace the Say() call with a PlaySound()).
Moreover, if I understood your request correctly, the messages are now triggered using the signal from LastValue(Ref(Buy, -1)) or LastValue(Ref(Sell, -1)).
This should happen when (what was till a few moments ago) the "last" candle is CLOSED, and a new "last" candle is now displayed on the chart (with LHC prices that change as per the RT feed).
Please, study the documentation of these two functions LastValue() and Ref() to see if this is what you wanted to achieve.
Ref() is used in the code also to set the "price" for the audio/visual alerts; note that there is nothing in the formula about the price to be used for Buy or Sell signals since this is not intended to be backtested.
function SayOnce( Text )
{
if( StaticVarGetText( "LastSay" ) != Text )
{
Say( Text, True );
StaticVarSetText( "LastSay", Text );
}
}
function PopOnce( msg, caption, timeout )
{
if( StaticVarGetText( "LastPop" ) != msg )
{
PopupWindow( msg, caption, timeout );
StaticVarSetText( "LastPop", msg );
}
}
function getSAPIAlias()
{
// if Alias field is defined use it instead of Name()
// otherwise get only the symbol part if symbol is in a format similar to sym-yyy-wwww-zzz (IB like)
// customize it as needed
alias = StrTrim( GetFnData( "alias" ), " " );
if( alias == "" )
{
alias = Name();
alias = StrExtract( alias, 0, '-' );
}
return ( alias );
}
// Fake rules to get frequent signals - Test done wih 1 minute bars
Buy = C > Ref( C, -1 );
Sell = C < Ref( C, -1 );
Buy = ExRem( Buy, Sell );
Sell = ExRem( Sell, Buy );
if( Status( "action" ) == actionIndicator )
{
sigPrice = LastValue( Ref( C, -1 ) );
_N( Title = StrFormat( "{{NAME}} - " + FullName() +
" - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) Vol " +
WriteVal( V, 1.0 ) + " {{VALUES}} - ", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( C, "Close", colorDefault, styleBar );
bi = BarIndex();
// No shape on last bar
shape = iif( ( bi == LastValue( bi ) ), Null, Buy * shapeUpArrow + Sell * shapeDownArrow );
PlotShapes( shape, IIf( Buy, colorBrightGreen, colorRed ), 0, IIf( Buy, L, H ), -25 );
if( LastValue( Ref( Buy, -1 ) ) )
{
PopOnce( "Buy Signal" + " " + Name() + " at " + sigPrice, "Buy Signal", 10 );
SayOnce( "Buy " + getSAPIAlias() + " at " + sigPrice );
// Show the last BUY price in the title (till the next bar arrives)
Title = Title + EncodeColor( colorBrightGreen ) + "Last Closed Signal " + sigPrice;
}
if( LastValue( Ref( Sell, -1 ) ) )
{
PopOnce( "Sell Signal" + " " + Name() + " at " + sigPrice, "Sell Signal", 10 );
SayOnce( "Sell " + getSAPIAlias() + " at " + sigPrice );
// Show the last SELL price in the title (till the next bar arrives)
Title = Title + EncodeColor( colorRed ) + "Last Closed Signal " + sigPrice;
}
}
// Exploration - to expand as needed
function nil( a )
{
return( IIf( a, a, Null ) );
}
barcomplete = BarIndex() < LastValue( BarIndex() );
Filter = 1;
AddColumn( nil( Buy ), " Buy ", 1.0 );
AddColumn( nil( Sell ), " Sell ", 1.0 );
AddColumn( nil( barcomplete ), "Complete", 1.0 );
SetSortColumns( -2 ); // most recent bar at top to see the barcomplete value
I hope you can use this example/info as a starting point to further develop your idea and above all as an inspiration to explore the rich set of AmiBroker functions.
For instance, why not use two voices (male and female) to distinguish Buy from Sell alerts better?
You may do it via VoiceCount() that will get the number of available SAPI voices and VoiceSelect() that will select the active one.
One more caveat. Search the forum to learn why, in general, it is essential to use "unique" names for your StaticVarSet variables (something that I guilty disregarded in the above example).
Did I mention that using AlertIf(), all in all, is simpler?