To send automated orders using Amibroker, one usually uses API-based trading solutions. API works on the concept of request and response. Every Place order request that we send from amibroker to the broker server is responded with a corresponding response message from the broker server (Order Successful, Order No, Error Messages, Session Expired, etc).

In this tutorial we are going to use Amibroker to measure the order latency
Trade Round Trip Time & Trade Latency
The round trip time is how long it takes for an order request sent from an Amibroker to the exchange via broker server, and for the response to get back to the original source(Amibroker). Basically, the latency in each direction, plus the processing time.
Latency measures how long it takes for order request from Amibroker (Source) to reach Exchange(destination host). Latency is often undesirable, and especially so in Automated Trading where speed and responsiveness are essential elements of the trading business.
The one with the lowest latency will be the first to get their order filled at the market price; those with higher latency are likely to pay a higher price for the same trading instrument by executing at market price.
How to Measure Order Execution Time using Amibroker GetPerformanceCounter Function
GetPerformanceCounter function can be a in trading system automation to measure time in milliseconds between various events. In our example we are going to use to measure the difference between the order request sent from Amibroker to the order confirmation response from the exchange via broker.
_TRACE("Broker Server Request : "+ api_data);
//enabling the counter before placing order request
GetPerformanceCounter(True); // reset counter to zero
response = openalgo.PlaceOrder("BUY", quantity);
//calculating the value of the counter after the order is placed
elapsedtime = GetPerformanceCounter()/1000;
_TRACEf("Broker Server Response : %s", response);
_TRACE("Broker API Reponse Time : "+elapsedtime+" secs");
Here is the simple Amibroker AFL Code to measure the Order response time.
use the parameter button controls to send the trading orders and order execution response time is calculated and displayed in Amibroker log window

//Code Generated using AFLGPT - www.marketcalls.in
_SECTION_BEGIN("OpenAlgo Button Trading with Param Triggers");
RequestTimedRefresh(1, False);
apikey = ParamStr("OpenAlgo API Key", "******");
strategy = ParamStr("Strategy", "Amibroker");
symbol = ParamStr("Symbol", "RELIANCE");
exchange = ParamList("Exchange", "NSE|NFO|BSE|MCX|CDS");
pricetype = ParamStr("Price Type", "MARKET");
product = ParamList("Product", "MIS|NRML|CNC");
quantity = Param("Quantity", 1, 1, 1000, 1);
buyTrigger = ParamTrigger("Buy Trigger", "Trigger Buy Order"); // Param trigger for Buy
sellTrigger = ParamTrigger("Sell Trigger", "Trigger Sell Order"); // Param trigger for Sell
host = ParamStr("Host", "http://127.0.0.1:5000");
ver = ParamStr("API Version", "v1");
VoiceAlert = ParamList("Voice Alert", "Disable|Enable", 1);
EnableAlgo = ParamList("Algo Mode", "Disable|Enable", 0); // Algo Mode
bridgeurl = host + "/api/" + ver;
static_name_ = Name() + GetChartID() + Interval(2) + strategy;
static_name_algo = static_name_ + Interval(2) + strategy + "algostatus";
// OpenAlgo Dashboard
GfxSelectFont("BOOK ANTIQUA", 14, 100);
GfxSetBkMode(1);
if (EnableAlgo == "Enable") {
AlgoStatus = "Algo Enabled";
GfxSetTextColor(colorGreen);
GfxTextOut("Algostatus : " + AlgoStatus, 20, 40);
if (Nz(StaticVarGet(static_name_algo), 0) != 1) {
_TRACE("Algo Status : Enabled");
StaticVarSet(static_name_algo, 1);
}
}
if (EnableAlgo == "Disable") {
AlgoStatus = "Algo Disabled";
GfxSetTextColor(colorRed);
GfxTextOut("Algostatus : " + AlgoStatus, 20, 40);
if (Nz(StaticVarGet(static_name_algo), 0) != 0) {
_TRACE("Algo Status : Disabled");
StaticVarSet(static_name_algo, 0);
}
}
EnableScript("VBScript");
<%
Public Sub PlaceOrder(action, quantity)
Dim oXMLHTTP
Dim oStream
Set oXMLHTTP = CreateObject("Msxml2.XMLHTTP")
Dim apikey, strategy, symbol, exchange, pricetype, product
apikey = AFL.Var("apikey")
strategy = AFL.Var("strategy")
symbol = AFL.Var("symbol")
exchange = AFL.Var("exchange")
pricetype = AFL.Var("pricetype")
product = AFL.Var("product")
Dim jsonRequestBody
jsonRequestBody = "{""apikey"":""" & apikey & _
""",""strategy"":""" & strategy & _
""",""symbol"":""" & symbol & _
""",""action"":""" & action & _
""",""exchange"":""" & exchange & _
""",""pricetype"":""" & pricetype & _
""",""product"":""" & product & _
""",""quantity"":""" & quantity & """}"
Dim url
url = AFL.Var("bridgeurl") & "/placeorder"
oXMLHTTP.Open "POST", url, False
oXMLHTTP.setRequestHeader "Content-Type", "application/json"
oXMLHTTP.setRequestHeader "Cache-Control", "no-cache"
oXMLHTTP.setRequestHeader "Pragma", "no-cache"
oXMLHTTP.Send jsonRequestBody
api_parameters = "Strategy :" & strategy & " Symbol :" & symbol & " Exchange :" & exchange & _
" Action :" & action & " Pricetype :" & pricetype & _
" Product :" & product & " Quantity:" & quantity & _
" api_url :" & url
AFL("api_request") = api_parameters
AFL("api_response") = oXMLHTTP.responseText
End Sub
%>
openalgo = GetScriptObject();
if (EnableAlgo == "Enable") {
if (buyTrigger) {
openalgo.PlaceOrder("BUY", quantity);
if (VoiceAlert == "Enable") {
Say("Buy Order Triggered");
}
_TRACE("API Request : " + api_request);
_TRACE("API Response : " + api_response);
}
if (sellTrigger) {
openalgo.PlaceOrder("SELL", quantity);
if (VoiceAlert == "Enable") {
Say("Sell Order Triggered");
}
_TRACE("API Request : " + api_request);
_TRACE("API Response : " + api_response);
}
}
_SECTION_END();
// Candlestick Chart Section
_SECTION_BEGIN("Candlestick Charts with Date & Time Axis");
SetChartOptions(0, chartShowArrows | chartShowDates);
Plot(Close, "Candle", colorDefault, styleCandle);
_SECTION_END();