Need little Help with alerts

HI I have basic crossover code to generate buy sell signals ,Currently it is giving audio alerts when the signals come. But i need it to give alert only one time when the candle closes. Please help

Code is -

_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
_SECTION_END();

SetBarsRequired( sbrAll, sbrAll );
SetChartOptions(2,chartShowArrows|chartShowDates|chartWrapTitle);
SetChartOptions(0,chartShowArrows|chartShowDates);

_SECTION_BEGIN("KPL Swing");
no=Param( "Swing", 20, 1, 55 );
tsl_col=ParamColor( "Color", colorCycle );

res=HHV(H,no);
sup=LLV(L,no);
avd=IIf(C>Ref(res,-1),1,IIf(C<Ref(sup,-1),-1,0));
avn=ValueWhen(avd!=0,avd,1);
tsl=IIf(avn==1,sup,res);


Buy=Cross(C,tsl);
Sell=Cross(tsl,C);


shape=Buy*shapeUpArrow + Sell*shapeDownArrow;
PlotShapes(shape,IIf(Buy,tsl_col,tsl_col),0,IIf(Buy,Low,High));


Buy = ExRem(Buy,Sell);
Sell = ExRem(Sell,Buy);

barcomplete = BarIndex() < LastValue(BarIndex());


if (Buy[BarCount-1]==True )
{
PopupWindow("Your Strategy has given a Buy Signal"+"  "+Name(),"Buy Signal",30);
PlaySound("C:\\Sound\\siren.wav"); 
}

if (Sell[BarCount-1]==True )
{
PopupWindow("Your Strategy has given a Sell Signal"+"  "+Name(),"Sell Signal",30);
PlaySound("C:\\Sound\\siren.wav"); 

}

_SECTION_END();

Moderator comment: added missing code tags

@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 :slight_smile:) 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 :smile:).

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?

11 Likes

I was going to set up AlertIf() to send a simple text message to my cell phone...

AlertIf( Buy, "", Name() + ">>>" + Close, 4 );

phonenumber@mms.wirelesscarrier.com

I tested the phonenumber@mms.wirelesscarrier.com formatting by sending the email from gmail to my phone and that works. I downloaded the SSLAddon.exe and moved the emailer from the 32bit directory to the 64 bit main Amibroker directory. Set it up using gmail and yahoo with 425 as the port and SSL checkbox checked and Both Gmail and Yahoo logins failed...
Question, it seems to me like I remember being able to justg send an SMTP from the laptop a long time ago. Is there a really simple config for this, without going thru email?
Thanks.

Use port 465 not 425.

22

Thanks, will try that.
Much appreciated.

Well, I tried that with port 465 and SSL checkbox Checked and got this response from gmail and yahoo mail... :frowning:
SMTP SMTP-Yahoo
Years ago, it used to work fine on the 32bit machine.

Obviously I am doing something wrong...

Suggestions?

Message comes from Gmail not from AmiBroker.
Google, Yahoo, ... prevent login from 3rd party tools by default.
So you have to enable it in your account settings at those mail providers.

As for Google... forum search is your friend

In addition check whether you have inserted correct password e.g. without spaces. So do not copy and paste.

Also be aware of mail limit as mentioned in upper thread.

Anyway, sending mail works fine on my end without issues.

You have to follow Knowledge Base:

Especially point 3 is important:

In certain cases the e-mails may be blocked by default Gmail account settings. If the authentication fails with an error message, it may be required to visit: https://www.google.com/settings/security/lesssecureapps and switch Access for less secure apps to Enable as shown below:

Oops.
Let me try that, thanks.

Hi @beppe , I am new to the forum and searched a lot about the issue but could not find the solution, I also got stuck with a similar situation where I am scanning multiple intraday strategies(AFLs) in different analysis windows on a basket of stocks. ALERTIF is a great functions but if sometime (only sometimes) buy signal comes from multiple strategies for the same stock, only one alert comes, it does not come for other strategies, as ALERTIF function skips the repeating signals. So how can I scan for strategywise non repeating signals. I am scanning the current candle in a loop of 10 secs.

Below is the code I am using to alert me on signals.

Buy = Cross(MACD(), Signal());
Sell = Cross(Signal(), MACD());

lpl = ValueWhen(Buy, C * 1.08);
lsll = ValueWhen(Buy, C * 0.96);

strategyName = "Intraday System A";
AlertIf(Buy, "EMAIL", strategyName+" Buy "+Name()+" "+C+" TGT "+lpl+" SL "+lsll, 1, 1+2+4+8, 0);
AlertIf(Sell, "EMAIL", strategyName+"Exit "+Name()+" Buy position "+C, 2, 1+2+4+8, 0);

@Smco , if I correctly understand your request, I fear that the AlertIf may not be the best choice to achieve your goal.
You surely have read the Using formula-based alerts document, and in particular the section about the "Internal logic":

Alertif function implements internal logic in the form of finite state machine that prevents repeated signals of the same type from occuring. State (i.e. the TYPE of last alert) is stored on PER-SYMBOL basis. So each symbol has its "last alert" attached.

So, if you are running multiple strategies and they at the same bar issue a signal for the same symbol, that signal by default is not repeated (i.e., skipped/silenced).

During experimentation you may prefer to get repeated signals in subsequent scans. To do so you should change default flags to 1 + 2

Did you try to play with the different flags? Is it too noisy? If so, I suspect that you have to write your own logic and employ some alternative methods to collect and display the alerts.

In any case, I'm probably not the best to give you ideas on this subject since I never scan the market in real-time (I only trade "slow" strategies).

I hope that some other traders that use AmiBroker for live trading will provide you better guidance.

You need to change the TYPE parameter in the AlertIF if they are coming from different stategies. Look at the User's manual Using formula-based alerts for detailed explanation. Alternatively you can just use SendEmail function that does not have any internal logic and just sends any email when you call it http://www.amibroker.com/f?sendemail

1 Like