Skip to content

Algo Control API

Launch, Stop, Configure and Monitor your algo remotely with our Algo Control API. Custom Field Names, Custom Field Types, Real-time GUI Updates.

Here are the steps to enable your algo to support GUI Algo Controls. 1. Implement nanoconda::listener class. 2. Fill nanoconda::guischema object with fields definitions. 3. Hanle start and stop signals via onuialgostart and onuialgostop callbacks. 4. Update GUI at any poinbt by calling setalgoreport().

Callbacks

Callback Listener

Communication between the algo and gui is implemented via callbacks from GUI (for example when a remote user presses a GUI button) and API calls (when algo needs to update GUI for the remote user).

In order to receive GUI callbacks, user must implement a listener class and inherit nanoconda::uilistener

Initialization
struct myListener : nanoconda::listener
{
      void onuischemarequest(guischema* schema) { };
      void onuialgostart(algorequest* algo) { };
      void onuialgostop(algorequest* algo) { };
   /* 
   ...
   */
}

...

int main(int argc, char *argv[])
{
   /*...*/

   myListener* l = new myListener();

   /*...*/
   nanoconda::dmasession* session = nanoconda::dmasession::init(account, rcode, cpu);

   /*...*/

   /*...*/
}

GUI Schema

In order for GUI to display algo custom fields user must define field descriptions (Schema). It must be done in onuischemarequest callback which will be raised whenever a User Starts Algo Window in GUI. The guischema* is passed as an argument and must be filled.

User must populate: 1. Number of Input Fields 2. Number of Algo Report Fields 3. Field Names and Types. 4. Optionaly, default, minimum, maximum and step values if user inputs should be limited or controlled.

nanoconda::fieldType enum
   enum fieldType : unsigned char
   {
      NC_BLANK=0,
      NC_C=1,
      NC_UC=2,
      NC_S=3,
      NC_US=4,
      NC_I=5,
      NC_UI=6,
      NC_P=7,
      NC_STR=9,
      NC_LL=10,
      NC_ULL=11,
      NC_F=12
   };
Field Description API
      template <typename T> void setField(const char* name, fieldType type, T deflt, T min, T max, T step );
      void setField(const char* name, fieldType type);

Note

deflt, min, max, step must be of same type.

Here is an example for creating a schema with 4 Input Fields, 3 Algo Report Fields and optional default, minimum, maximum and step arguments configured.

void onuischemarequest(nanoconda::guischema* schema)
{
   schema->inputFieldCount = 4;
   schema->inputFields[0].setField("Input1", nanoconda::NC_F, 100.123, 10.0, 200.5, 10.0);
   schema->inputFields[1].setField("Input2", nanoconda::NC_LL, 200, 0, 200, 7);
   schema->inputFields[2].setField("Input3", nanoconda::NC_F, -30.0, -20.0, 200.0, 11.0);
   schema->inputFields[3].setField("Input4", nanoconda::NC_I, 400, -998, 222, 23);

   schema->algoFieldCount = 3;
   schema->algoFields[0].setField("AlgoField1", nanoconda::NC_F);
   schema->algoFields[1].setField("AlgoField2", nanoconda::NC_UI);
   schema->algoFields[2].setField("AlgoField2", nanoconda::NC_I);
}

Once provided, GUI will display such Schema:

GUI Schema

Launching and Stopping Algos

Once Schema is displayed user can set input parameters and Launch Algos with them. Whenever 'Launch Algo' button is clicked user application will receive the onuialgostart() callback. algo object will be provided a unique algoId for each Launched Algo.

Here is a sample implementation where we send a Buy market order for any new algo launch, save the new algo data internally and add a new line to the Algo Report with custom fields to update GUI with information that the algo is running.

void onuialgostart (nanoconda::algorequest* algo)
{

   nanoconda::order od;
   nanoconda::order* o = &od;
   o->setSymbol("MNQH5");
   o->quantity = 10;
   o->type = nanoconda::orderType::MKT;
   o->side= 'B';
   nanoconda::reasoncode code = _session->newOrder(o);

   if (code == nanoconda::SUCCESS)
   {
      nanoconda::algorecord* adata = &_areport.algos[_areport.algoCount]; //_areport is an internally saved nanoconda::algoreport object;
      adata->algoId = algo->algoId;
      adata->fields[0]._f((float) _areport.algoCount);
      adata->fields[1]._ui( _areport.algoCount * 10);
      adata->fields[2]._ui( _areport.algoCount * 20);


      _areport.algoCount++;
      _session->setalgoreport(&_areport);

   }
}

If nanoconda::algoreport contains algos (nanoconda::algoreport::algoCount > 0) the lines will be displayed in GUI.

GUI Algos

Whenever X is pressed onuialgostop() callback will be raised. algo object will contain algoId and algoIndex of the relevant line in GUI algo report which should be used to indicate which algo received a stop signal.

Here is an example implementation of onuialgostop() where we send an opposing Sell market order and remove an algo line from internal and GUI algo reports.

void onuialgostop (nanoconda::algorequest* algo)
{
   nanoconda::order od;
   nanoconda::order* o = &od;
   o->setSymbol("MNQH5");
   o->quantity = 10;
   o->type = nanoconda::orderType::MKT;
   o->side= 'S';
   nanoconda::reasoncode code = _session->newOrder(o);

   if (code == nanoconda::SUCCESS)
   {
      int maxAlgos = 30;
      if(algo->algoIndex < maxAlgos-1)
      {
         memmove(&(_areport.algos[algo->algoIndex]),&(_areport.algos[algo->algoIndex+1]), sizeof(nanoconda::algorecord) * (maxAlgos - (algo->algoIndex+1)));
      }
      memset(&(_areport.algos[maxAlgos-1]),0x0,sizeof(nanoconda::algorecord));
      _areport.algoCount--;

      _session->setalgoreport(&_areport);
   }
}

Note

There are no requirements to how onuialgostart() or onuialgostop() callbacks should be implemented. They serve as communication with a remote GUI user. For example user can ignore the some callbacks completely or create / delete multiple algo report lines in a single callback.

Updating Algo Report

We gave some examples on how to update GUI via calling setalgoreport() with information about new and deleted algos in previous sections.

The beauty of setalgoreport() is that it can be called from anywhere in your algo code.For example on order confirmations, executions or book updates. This can help pass real-time updates for each algo. Some useful information might be the real-time PNL of a specific algo or average price.

Gui data refresh rate is 4x a second, so there is no need to set setalgoreport() more frequently (even though it is allowed).

A recommended approach to updating the GUI state is to have a separate thread that periodically updates the GUI with user internally kept algoreport:

pthread_t gui_pub_trhead;
pthread_create(&gui_pub_trhead, NULL, guiPublisher, myListener);

...


void* guiPublisher(void* data) 
{
    myListener* l = (myListener*) myListener;
    if(!l) return NULL;
    if(!l->_session) return NULL;

    while (1) {
       l->_session->setalgoreport(&l->_areport)
       usleep(250000); //sleep for 250 milliseconds
    }
    return NULL;
}

Sample Algo: Brackets

The NanoConda package includes a sample trading algorithm called Brackets. This algo is designed as a simple example to demonstrate how to build trading strategies using the NanoConda API. It is also a useful template for developers starting custom algo development.

The Brackets algo extends the base prototype defined in:

include/nanoconda_prototypes.h

Behavior

When launched from the GUI, the Brackets algo performs the following cycle:

  1. Sends a Market order in the direction selected by the user.
  2. After the fill is confirmed, it sends a bracket consisting of:

    • One Limit order (take profit)
    • One Stop Loss order (risk protection)
  3. When either of the bracket orders is filled:

    • The position is fully closed
    • The algo immediately restarts the cycle by opening a new position with another Market order

This shows how an algo can remain continuously active until explicitly stopped by the user.

Note

The Brackets algo is intended as a reference implementation only. Its logic is fully customizable. Users are free to:

- Modify the trading workflow
- Configure custom bracket logic
- Add risk or position sizing rules
- Control when algo lines are added or removed in the GUI
- Maintain any number of simultaneous algo instances

Tip

The above logic is all implemented inside the client code and is fully custom. User is free to chose how many algo lines are present in the report and when any line is added or removed.

Starting the Algo

To compile bracketsalgo please execute the following commands:

cd src/
make bracketsalgo
running bracketsalgo
Usage: ./bracketsalgo -e exchange -s symbol1,symbol2,... -u username -p password [-a account] [-c cpu]

./bracketsalgo -e XCME -s ESM5,NQM5 -u hftclient -p password -a hftclientAcc100

Note

Please replace command line arguments for your use case.

GUI Controls

The Brackets algo can be controlled directly from the NanoConda GUI:

Action Description
Launch Starts the algo and begins trading
X (Stop) Stops the algo and closes open positions safely
Remove Clicking X again when status is CANCEL removes it from the report

Tip

After stopping, the algo status transitions to CANCEL, but it remains visible so the user can review metrics such as algo P&L and lifecycle events.

Brackets Algo

Notes:

  1. Algo is Online indicates that the application is running and connected.
  2. The first row shows Algo Status = CANCEL, meaning this algo was stopped via the API.
  3. The second row shows Algo Status = ON, meaning the algo is currently active and trading.
  4. Custom algo Names were provided at launch to clearly identify which algo trades in which direction.
  5. The active algo has linked Stop and Profit orders visible, and these can also be confirmed in the Live Orders window.