How to act on actual entry exit signals instead of coded signals?

Hello,
This question is regarding placing actual trades by calling InternetPostRequest.
In order to call this function from AFL, I need some logic in place to invoke it and pass correct values like is it a Buy trade or short, what price, which symbol, etc.
The problem is how can I have Entry and Exit signals shown in the Detailed Log of backtester in AFL?
I have PositionScore and Buy, Short, Sell Cover variables. Using them I tried to put some logic as shown in the below code, but that is definitely not equal to how entry and exit signals are generated. Because Amibroker is doing something smart. It's using PositionScore and Position Sizing along with Buy sell signals to generate these Entry-Exit signals. How can I incorporate those signals in my code so that at those events I can call InternetPostRequest ?

Here is my code:

SetBacktestMode( backtestRegular );
Buy = Sell = Short = Cover = 0;
fastPeriod = 7;
rank = 12;
maxPositions = 4;

fast = MA( Close, fastPeriod );
slow= MA( Close, 15);

SetOption("worstrankheld", rank); 
SetOption("Maxopenpositions", maxPositions); 
SetOption("allowpositionshrinking", True);

PositionSize = -(100/maxPositions); 

PositionScore = fast - slow;  // Use Ranking over 30 stocks

Plot(PositionScore,"PositionScore",colorGold,styleCandle);

Buy = Cross(fast,slow);
Short = Cross(slow, fast);
Cover = PositionScore > 0;  // Or just use Cover = Buy ?
Sell = PositionScore < 0;  // Or just use Sell = Short ?

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

sym =Name();
view = "noview";

AlgoBuy = LastValue(Ref(Buy,0));
AlgoShort = LastValue(Ref(Short,0));
AlgoCover = LastValue(Ref(Cover,0));
AlgoSell = LastValue(Ref(Sell,0));

headers = "Content-Type: application/json\r\n" +
          "Accept-Encoding: gzip, deflate\r\n";
          
InternetSetHeaders(headers); 

if (AlgoBuy == True) {
    view = "buy";
}
if (AlgoSell == True) {
	view = "sell";
}	
if (AlgoShort == True) {
	view = "short";
}		
if (AlgoCover == True) {
	view = "cover";
}
api_data ="{\"symbol\":"+ "\""+sym+"\",\"view\":"+ "\""+view+"\",\"price\":"+ "\""+Close+"\",\"paperTrade\":"+ "\"true\"}";
//Call the Broker API endpoint to place Order
if (view != "noview") {
	ih = InternetPostRequest("https://order-execution.com/stocks/orders/", api_data, 1);
	if( ih )
	{
		 while( ( str = InternetReadString( ih ) ) != "" )
		 {
			 _TRACEF( "%s", str );
		 }
		 InternetClose( ih );
	}
}
AlertIF( True, "", "Actual Trade Initiated for " + sym , 0);

In the above code, I am trying to send data to the order execution application based on the Buy-Sell condition.
But something is not correct there as it doesn't consider PositionScore.

Here is attached snipped of detailed log:
image

The entry and exit signals do not match the logic of variables AlgoBuy, AlgoShort, AlgoCover, and AlgoSell. Because entries and exists also have some logic going on behind the scenes. How do I use that logic in my code?
Regards

Additional info: I tried initially using StaticVarGenerateRanks but it looks like it doesn't work the way PositionScore works. But if that is the way to solve my problem, then even a resolution on that thread would do.

This is what the real-time scanning signals look like, they are not exactly how backtest would generate because backtest is considering PositionScore too. These signals are simply generated using Buy and Sell variables. This is my problem.
image

I am thinking in a reverse way, as in, what is it that would solve my problem. Here is a code snippet that will do what I need.

PositionSize = -25;
PositionScore = RSI(14);
Buy = Cover =  Cross(MA(Close, 3), MA(Close, 15));
Short = Sell = Buy = Cross(MA(Close, 15), MA(Close, 3));
symbol = Name();
entryOrExit = GetGeneratedSignal();  // Function returns entry or exit signal based on Buy Sell 
// coondition and PositionScore, PositionSize for current symbol, in addition to collectively 
// looking at other symbols  under scanner. Possible values of entryOrExit : "EnterLong", "ExitShort", "EnterShort", "ExitLong". 

ALERTIF(entryOrExit  != "",  "", "Signal generated for symbol " + symbol + "  Is it Entry or Exit? " + entryOrExit , 0 );

The function "GetGeneratedSignal" used above is just hypothetical, Do we have such kind of function or any way to achieve what that function is doing?

Your code is wrong in number of places.

  1. Ref() with zero offset does nothing (you should remove it)
  2. Your code would produce repetitive orders if you run it twice or more within same bar
  3. The purpose of backtest is to test HISTORICALLY. Real time trading is other story. Read UserKB for some information AmiBroker Users' Knowledge Base
  4. If you want to use position score in your code and use backtester (which is not really meant to do this) to generate your "actual trades", you have to use custom backtest code
    Porfolio Backtester Interface Reference

Overall judging from the quality of code that you have provided I would say you need at least 1 year of learning to be able to write the code to automate trading, especially if you are NOT using automated trading interface (IBController 1.3.8 READ ME) and you want to roll your own solution based on low-level http requests sent directly from code.
At this moment this is beyond your skill set. If you want it "now" you have to hire somebody with appropriate skills.

Still it is advised to learn yourself. You absolutely must understand the code you are putting your money on.
To get better understanding of what is happening in your code and how functions work, use advice given here: How do I debug my formula?

2 Likes

Thanks, @Tomasz I will put effort into the directions you have given.

I was able to resolve my actual problem of how to trade real-time with PositionScore with the help of in-built features provided by Amibroker, thanks to the various link provided by @Tomasz . I am putting the steps here just in case someone finds it useful.

If you only have PositionScore as deciding factor for trades in your AFL then Auto Scan will not give any signals because PositionScore works only with Backtester. So instead of using Autoscan, we can use Batch functionality in which we can set up periodic (Timeframe) Backtest of the recent bars (enough to be required by a look back period of indicators used in AFL).
In my case, for moving an average of 15 bars for 15 minutes, I need at least "2 recent days".
Step1: First create an analysis file with required bars to scan
scan-setting

Step2: Set up a Batch scan that will load the above analysis file and AFL. Provide three actions.
Load Project, Backtest, and then Export to file. Make sure that "Detailed Log" is turned on in settings to get nice Entry-Exit signals in the CSV file, which can be parsed by a program in Python or Java or any other language for executing orders.
Batch-scan

Step3: Set up schedules of the Batch file as per timeframe. For me, it is 15 mins so I had to set it up like below. I have given some delay of 35 to 40 seconds as it takes some time to get the data of the last candle.
schedules

That is it. After every 15 minutes, the batch scan triggers, it backtests on the latest 2 days of data including the latest fully formed candle and outputs the result to a CSV file. This set up is working perfectly well for the last 5 days.
I am new to Amibroker so it's possible that this may not be the perfect way to get the trades, so will be happy to know the better options.

1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.