Your interactive trading laboratory!
 • 
16 users online

Documentation of Broker Connection API
This is a Feature Request with 1 vote

Could you please publish some documentation of Quantacula's Broker Connection API?

Attachment

Cancel

Responses

Working on this today!

Working on this today!

It's available ...

https://www.quantacula.com/Help/OpenHelp/extapi/946

It's available ... [https://www.quantacula.com/Help/OpenHelp/extapi/946](https://www.quantacula.com/Help/OpenHelp/extapi/946)

Greta! Thanks!

However, I miss a Hook to open a nice GUI for broker specific settings.

Greta! Thanks! However, I miss a Hook to open a nice GUI for broker specific settings.

Let me work on that!

Let me work on that!

To connect to my Broker, there is an async Connect method:

async Task ConnectAsync();

If I try to call such an async Method from the Broker API's Connect Method like this:

ConnectAsync().Wait();

Quantacula freezes.

What is the correct method to call an async method from the Broker API?

To connect to my Broker, there is an async Connect method: [CODE] async Task ConnectAsync(); [/CODE] If I try to call such an async Method from the Broker API's Connect Method like this: [CODE] ConnectAsync().Wait(); [/CODE] Quantacula freezes. What is the correct method to call an async method from the Broker API?

It looks like we will have to provide async connect support. But until that's in place, you'll probably have to (I know it's ugly) write a while loop that cycles until the async connection completes and can write its status to some kind of flag variable that is examined in the loop.

It looks like we will have to provide async connect support. But until that's in place, you'll probably have to (I know it's ugly) write a while loop that cycles until the async connection completes and can write its status to some kind of flag variable that is examined in the loop.

I already tried this, but unfortunately Quantacula freezes as soon as I call this:

Task t = ConnectAsync();

And I guess all these other calls (MyBroker.PlaceTrade(), etc) are async as well...

You should have something to do async calls inside Quantacula. Isn't there a way to expose this "something" to the Broker API, probably as a member of IHost?

I already tried this, but unfortunately Quantacula freezes as soon as I call this: [CODE] Task t = ConnectAsync(); [/CODE] And I guess all these other calls (MyBroker.PlaceTrade(), etc) are async as well... You should have something to do async calls inside Quantacula. Isn't there a way to expose this "something" to the Broker API, probably as a member of IHost?

I found a solution here:

I call the async methods with an helper class to make it a sync call:

bool result = AsyncHelper.RunSync(() => ConnectAsync());

This works nicely inside the Broker Adapter.

The Helper class looks like this:

public static class AsyncHelper
{
        private static readonly TaskFactory _taskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None,
            TaskContinuationOptions.None, TaskScheduler.Default);

        public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

        public static void RunSync(Func<Task> func)
            => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}
I found a solution [here](https://cpratt.co/async-tips-tricks/): I call the async methods with an helper class to make it a sync call: [CODE] bool result = AsyncHelper.RunSync(() => ConnectAsync()); [/CODE] This works nicely inside the Broker Adapter. The Helper class looks like this: [CODE] public static class AsyncHelper { private static readonly TaskFactory _taskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); public static TResult RunSync<TResult>(Func<Task<TResult>> func) => _taskFactory .StartNew(func) .Unwrap() .GetAwaiter() .GetResult(); public static void RunSync(Func<Task> func) => _taskFactory .StartNew(func) .Unwrap() .GetAwaiter() .GetResult(); } [/CODE]

Someone on the internet mentions:

FuncAsync().Wait();

This code will always deadlock if executed within a task created on the main UI thread by a new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()).

Someone on the internet mentions: [CODE] FuncAsync().Wait(); [/CODE] This code will always deadlock if executed within a task created on the main UI thread by a new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()).

Awesome, thank you for sharing this, it's really handy!

Awesome, thank you for sharing this, it's really handy!

Next question:
Inside my broker adapter, how can I find out if the symbol of the transaction is a stock or future and so on?

Next question: Inside my broker adapter, how can I find out if the symbol of the transaction is a stock or future and so on?

I'd suggest you add this to the Broker Adapter API Documentation:


If you need to poll your broker on a regular basis in order to update the order stati follow these step:

First you have to tell Visual Studio that your broker adapter will run with Quantacula Studio only.
Quantacula Studio is a .Net Core 3.1 Windows Desktop WPF Application. So modify your myBroker.csproj File to read:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
     <UseWPF>true</UseWPF>
    ...

Now the System.Windows.Threading namespace is available:

using System.Windows.Threading;

Create, initialize and start a DispatcherTimer in your Initialize() method:

            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 3); // call dispatcherTimer_Tick every three seconds
            dispatcherTimer.Start();

This calls dispatcherTimer_Tick every three seconds (approximately). In this routine you can update Quantaculas pending transactions:

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    Host.DisplayBrokerMessage(Name + ": Timer Elapsed");

    // request updated status from Broker
   ...
    
    // if a fill happened you can:
     t.FillPrice = fillPrice;
     t.FillQty = fillQuantity;
     if(t.FillQty == t.Quantity) newStatus = SignalStatuses.Filled;
     else newStatus = SignalStatuses.PartialFilled;
     ...
     if (t.SignalStatus != newStatus || otherChange)
     {
             this.UpdateSignalStatus(t, newStatus);
     }
}

This will update the information in Quantacula's SignalHub.

I'd suggest you add this to the Broker Adapter API Documentation: ----------------------- If you need to *poll* your broker on a regular basis in order to update the order stati follow these step: First you have to tell Visual Studio that your broker adapter will run with Quantacula Studio only. Quantacula Studio is a .Net Core 3.1 Windows Desktop WPF Application. So modify your <tt>myBroker.csproj</tt> File to read: [CODE] <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <UseWPF>true</UseWPF> ... [/CODE] Now the <tt>System.Windows.Threading</tt> namespace is available: [CODE] using System.Windows.Threading; [/CODE] Create, initialize and start a <tt>DispatcherTimer</tt> in your <tt>Initialize()</tt> method: [CODE] DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); dispatcherTimer.Interval = new TimeSpan(0, 0, 3); // call dispatcherTimer_Tick every three seconds dispatcherTimer.Start(); [/CODE] This calls <tt>dispatcherTimer_Tick</tt> every three seconds (approximately). In this routine you can update Quantaculas pending transactions: [CODE] private void dispatcherTimer_Tick(object sender, EventArgs e) { Host.DisplayBrokerMessage(Name + ": Timer Elapsed"); // request updated status from Broker ... // if a fill happened you can: t.FillPrice = fillPrice; t.FillQty = fillQuantity; if(t.FillQty == t.Quantity) newStatus = SignalStatuses.Filled; else newStatus = SignalStatuses.PartialFilled; ... if (t.SignalStatus != newStatus || otherChange) { this.UpdateSignalStatus(t, newStatus); } } [/CODE] This will update the information in Quantacula's SignalHub.

Synchronization 1: Total Equity

If Quantacula is used to drive a broker's account it is desirable to have TotalEquity at the end of a backtest match the account's total equity closely in order to calculate the correct position sizes for this account.

How is this supposed to work?

I see a GetAccountEquity() method in the Broker API. When is this called? How is this used?


Some thougts:

The accoumt's total equity is an undeniable fact, so in this case the startegies total equity has to adapt.
The free parameter to achieve this is starting capital of the strategy.

To make this work the broker adapter needs to know when a backtest has finished. Then it needs a way to modify the connected startegies starting capital. Then all staged orders must be canceled and the backtest must run again.

Any better ideas?

### Synchronization 1: Total Equity If Quantacula is used to drive a broker's account it is desirable to have TotalEquity at the end of a backtest match the account's total equity closely in order to calculate the correct position sizes for this account. How is this supposed to work? I see a <tt>GetAccountEquity()</tt> method in the Broker API. When is this called? How is this used? ---- Some thougts: The accoumt's total equity is an undeniable fact, so in this case the startegies total equity has to adapt. The *free parameter* to achieve this is starting capital of the strategy. To make this work the broker adapter needs to know when a backtest has finished. Then it needs a way to modify the connected startegies starting capital. Then all staged orders must be canceled and the backtest must run again. Any better ideas?

I'd suggest you add the following text to the broker adapter documentation:


The Life of an Order

An order is generated by a strategy or manually in Signal Hub.
The order appears in Signal Hub with Status Staged.

At this point the order can be removed in Signal Hub but not cancelled.

The user clicks "Submit" or "Submit Selected" in Signal Hub.

PlaceTrade() is called and should send the order to the broker.
If the order is accepted by the broker, PlaceTrade() calls
UpdateSignalStatus(t, SignalStatuses.Published)

In Signal Hub the order is shown with status Published.

At this point the order can be removed in signal hub but not cancelled.

Inside the Broker Adapter you should find out if the order is accepted by the Broker. If the broker accepts the order, then as long as the order is not active (e.g. outside trading hours) you call
UpdateSignalStatus(t, SignalStatuses.Placed)
if the order is active (working) on the exchange you call
UpdateSignalStatus(t, SignalStatuses.Active)

It seems not possible to have a transition form Published to Active. So you need to call
UpdateSignalStatus(t, SignalStatuses.Placed)
if the transaction is still in status Published, before you can set the status to Active.

In Signal Hub the order is now shown with Status Placed or Active.
Now the order can be cancelled.

If the order is cancelled in Signal Hub CancelTrade() is called.
You should cancel the order in the Broker Adapter/at your broker and call
UpdateSignalStatus(t, SignalStatuses.CancelPending);

Now the order is shown with status CancelPending in Signal Hub.

Inside your Broker Adapter you should check if the order is cancelled at the broker.
If you detect that the order is canceled (or expired) you call
UpdateSignalStatus(t, SignalStatuses.Canceled);

Now the order is shown with status Canceled in Signal Hub.

If the order is not canceled it will get filled. As soon as you detect that the order is filled, you call
UpdateSignalStatus(t, SignalStatuses.PartialFilled);
or
UpdateSignalStatus(t, SignalStatuses.Filled);

Now the order is shown with status PartiallyFilled or Filled in Signal Hub.

I'd suggest you add the following text to the broker adapter documentation: ---- ### The Life of an Order An order is generated by a strategy or manually in Signal Hub. The order appears in Signal Hub with Status **Staged**. At this point the order can be removed in Signal Hub but not cancelled. The user clicks "Submit" or "Submit Selected" in Signal Hub. <tt>PlaceTrade()</tt> is called and should send the order to the broker. If the order is accepted by the broker, <tt>PlaceTrade()</tt> calls <tt>UpdateSignalStatus(t, SignalStatuses.Published)</tt> In Signal Hub the order is shown with status **Published**. At this point the order can be removed in signal hub but not cancelled. Inside the Broker Adapter you should find out if the order is accepted by the Broker. If the broker accepts the order, then as long as the order is not active (e.g. outside trading hours) you call <tt>UpdateSignalStatus(t, SignalStatuses.Placed)</tt> if the order is active (working) on the exchange you call <tt>UpdateSignalStatus(t, SignalStatuses.Active)</tt> _It seems not possible to have a transition form Published to Active. So you need to call_ <tt>UpdateSignalStatus(t, SignalStatuses.Placed)</tt> _if the transaction is still in status Published, before you can set the status to Active._ In Signal Hub the order is now shown with Status **Placed** or **Active**. Now the order can be cancelled. If the order is cancelled in Signal Hub <tt>CancelTrade()</tt> is called. You should cancel the order in the Broker Adapter/at your broker and call <tt>UpdateSignalStatus(t, SignalStatuses.CancelPending);</tt> Now the order is shown with status **CancelPending** in Signal Hub. Inside your Broker Adapter you should check if the order is cancelled at the broker. If you detect that the order is canceled (or expired) you call <tt>UpdateSignalStatus(t, SignalStatuses.Canceled);</tt> Now the order is shown with status **Canceled** in Signal Hub. If the order is not canceled it will get filled. As soon as you detect that the order is filled, you call <tt>UpdateSignalStatus(t, SignalStatuses.PartialFilled);</tt> or <tt>UpdateSignalStatus(t, SignalStatuses.Filled);</tt> Now the order is shown with status **PartiallyFilled** or **Filled** in Signal Hub.

Much appreciated! I am working on adding the async connection methods to the BrokerBase class and implementing TD Ameritrade. Once that's done and released I will update the documentation including your gracious additions :)

Much appreciated! I am working on adding the async connection methods to the **BrokerBase** class and implementing TD Ameritrade. Once that's done and released I will update the documentation including your gracious additions :)

Very Good!

But please note there were two questions of mine in the posts above...

Very Good! But please note there were two questions of mine in the posts above...

To make my broker adapter more feature-complete it would be helpfull to have the following features in the Broker Adapter API:


Notification of End of Backtest

Whenever a backtest finishes, the currently choosen broker adapter should receive a notification. This should come before the first PlaceTrade() is called after a backtest.

Access to currently open positions

From inside the broker adapter it should be possible to access all open positions in the model/backtest which is connected to the broker adapter.

Populate Signal Hub with Orders generated by the Broker Adapter

Similar to manual orders it should be possible to add some orders to Signal Hub from the Broker Adapter.


These features work in concert and would allow (among many other things) for a completely automatic but transparent synchronization of positions and orders between a Quantacula model and its realtime / real life counterpart in a broker account.

To make my broker adapter more feature-complete it would be helpfull to have the following features in the Broker Adapter API: *** ### Notification of End of Backtest Whenever a backtest finishes, the currently choosen broker adapter should receive a notification. This should come *before* the first <tt>PlaceTrade()</tt> is called after a backtest. ### Access to currently open positions From inside the broker adapter it should be possible to access all open positions in the model/backtest which is connected to the broker adapter. ### Populate Signal Hub with Orders generated by the Broker Adapter Similar to manual orders it should be possible to add some orders to Signal Hub from the Broker Adapter. *** These features work in concert and would allow (among many other things) for a _completely automatic but transparent_ synchronization of positions and orders between a Quantacula model and its realtime / real life counterpart in a broker account.
Forum Tips

Please sign in if you want to participate in our forum.

Our forum uses Markdown syntax to format posts.

To embed code snippets, enclose them in [CODE][/CODE] tags.