How to Execute Strategy in .NET
Contents
- 1 Overview
- 2 What Do You Need for a Strategy?
- 3 Classes Used by Application Executing a Strategy
- 4 Step #1. Add Indicore Integration SDK and Order2Go to the Project
- 5 Step #2. Providing Helper .Lua Files for Standard Strategies
- 6 Step #3. Initializing Indicore Integration SDK and Order2Go
- 7 Step #4. Subscribe to Price History Events
- 8 Step #5. Subscribe to Request Events
- 9 Step #6. Login to Trade Desk
- 10 Step #7. Load a List of Indicators and a List of Strategies
- 11 Step #8. Get a Strategy Profile
- 12 Step #9. Get an Instance of Startegy Parameters and Fill It with Values
- 13 Step #10. Implement Host Class
- 14 Step #11. Create an Object of the Host class, and Set it as a Host for Indicore Manager Object
- 15 Step #12. Implement a StrategyCallback class
- 16 Step #13. Create an object of StrategyCallback
- 17 Step #14. Implement IndicatorTickSource
- 18 Step #15. Implement IndicatorBarSource
- 19 Step #16. Get and Keep Price Streams
- 20 Step #17. Prepare Tick Sources for the Strategy
- 21 Step #18. Keep Information about Orders
- 22 Step #19. Create Strategy Instance
- 23 Step #20. Attach "Bid" and "Ask" Streams to History Manager
- 24 Step #21. Watch for New Prices
- 25 Step #22. Watch for Price History Events
- 26 Step #23. Watch for Request Events
- 27 Sample Project
- 28 This Article in Other Languages
Overview
The sample program is a console application executing strategy on live data. It uses Indicore Integration SDK and Order2Go. It prints live data on the screen and alerts user about appearing signals. If strategy is alowed to trade, the program would create trading orders.
What Do You Need for a Strategy?
In order to create a strategy instance you need a strategy profile, two alive tick streams ("bid" and "ask"), strategy parameters, and a callback function which would be called when a signal ("Buy" or "Sell") appears or trading order has to be created.
Classes Used by Application Executing a Strategy
These are the main classes used by application:
The main class Program
is responsible for loading a list of indicators and strategies, getting an indicator’s profile, and filling parameters for a strategy. It creates an instance of the strategy (an object of StrategyInstance
class) implemented as MyStrategyInstance
. Strategy instance always uses two tick sources (“bid” and “ask”), so you need to implement
IndicatorTickSource
class (MyIndicatorTickSource
class in the example). Some strategies may use time frames other than “tick”. It means you will need to implement
IndicatorBarSource
class (MyIndicatorBarSource
class in the example). Classes IndicatorTickSource
and
IndicatorBarSource
are subclasses of IndicatorSource
.
Strategy uses
Host
class for host application. Class MyHost
implements
Host
in the example. It is used to execute commands or to get data which are not covered by the standard interface of the indicators or the strategies.
Strategy instance needs a callback function for trading signals and executing orders sent from the strategy, that’s why you have to implement StrategyCallback
class (MyStrategyCallback
class in the example). Program will notify strategy instance when asynchronous operations requested by strategy are completed.
Let’s have a look at MyHost
class:
When MyHost
gets commands getTradingDayOffset
, getTradingWeekOffset
or getTradingProperty
, it calls Order2Go
class. For getHistory
commands MyHost
is using HistoryMgr
class. For setTimer
and killTimer
commands MyHost
is using TimersMgr
class.
We already mentioned that strategy always uses two tick streams (“bid” and “ask”), and some strategies use bar streams (“hourly” candles, “weekly” candles, etc.) Look at the streams’ creation and usage on the class diagram:
History manager can create either MyIndicatorTickSource
or MyIndicatorBarSource
(MyIndicatorBarSource
uses helper class BarData
). History Manager keeps information about streams created for the strategy instance via Ticket
class.
Class Order2Go
is used for getting trading property, trading day offset, trading week offset, and price history helper (the last is used for getting a candle for specific time). When MyHost
gets command findTable
, it returns TradingDataTable
. Class MyTradingTable
implements TradingDataTable
and contains information about trading tables (“Accounts”, “Offers”, “Orders”, “Trades”, “Closed Trades”, “Summary”, “Messages”). Class MyTradingTable
also uses MyTradingRowEnumerator
(subclass of TradingDataTableEnumerator
) and MyTradingRow
(subclass of TradingDataTableRow
).
Step #1. Add Indicore Integration SDK and Order2Go to the Project
To find out how to add Indicore Integration SDK to your .NET project please read the Start Using Indicore Integration SDK in .NET article. To find out how to add Order2Go to your .NET project please read C Sharp (O2GO) article.
Step #2. Providing Helper .Lua Files for Standard Strategies
If you are going to use standard strategy, you will need to create strategies\standard\include
structure in the target directory and copy files from strategies\standard\include
folder there
Step #3. Initializing Indicore Integration SDK and Order2Go
Initialize Indicator Core, Order2Go, and create trade desk object '"`UNIQ--toggledisplay-00000000-QINU`"'
Step #4. Subscribe to Price History Events
Some strategies have getHistory
requests (they may need history from time frame other than “tick”). Accomplishment of these requests takes time, so you would need to use asynchronous functions.
Subscribe to events OnPriceHistoryCompleted
and OnPriceHistoryFailed
'"`UNIQ--toggledisplay-00000001-QINU`"'
Step #5. Subscribe to Request Events
Strategies can be allowed to trade. Creating trading orders should be done asynchronously as well. Subscribe to events OnRequestCompleted and OnRequestFailed
'"`UNIQ--toggledisplay-00000002-QINU`"'
Step #6. Login to Trade Desk
Log in using your user ID, password, URL, and connection ("real" or "demo") '"`UNIQ--toggledisplay-00000003-QINU`"'
Step #7. Load a List of Indicators and a List of Strategies
To find out how to initialize core and load indicators please read the How to Load Indicators in .NET article. Do similar steps to load strategies.
Step #8. Get a Strategy Profile
First of all you have to find the profile of the strategy to be created. Usually, strategies are referred by their identifier. For example "MA_ADVISOR" for Sample Moving Average strategy. In fact, the identifier is just a file name of the strategy without the extension and used in the upper case.
The profile is used to:
- Get human-friendly name and description of the strategy.
- Get the list of the parameters.
To enumerate the profiles or find them, you must use an instance of the StrategiesCollection
class. Let's find the Sample Moving Average (MA_ADVISOR) strategy.
'"`UNIQ--toggledisplay-00000004-QINU`"'
Step #9. Get an Instance of Startegy Parameters and Fill It with Values
The strategy profile can be used to get the set of the parameters of the strategy. You can fill this parameter set or just use the default values. In the last case you can just pass null instead of the parameter set for creating strategy instance. Let's set the FMA_N (number of periods for fast moving average) to 6, and SMA_N (number of periods for slow moving avarage) to 20. For the strategy MA_ADVISOR used in the example you would need to set parameter CANTRADE to “Yes”, and parameter ACCOUNT to account ID in case the strategy is allowed to trade.
'"`UNIQ--toggledisplay-00000005-QINU`"'
Step #10. Implement Host Class
This class is used to execute the commands or get the data which are not covered by the standard interface of the indicators or the strategies. '"`UNIQ--toggledisplay-00000006-QINU`"'
Step #11. Create an Object of the Host class, and Set it as a Host for Indicore Manager Object
'"`UNIQ--toggledisplay-00000007-QINU`"'
Step #12. Implement a StrategyCallback class
Strategy uses StrategyCallback
for “Buy” and “Sell” signals (sending alerts) and for executing trading orders if trading is allowed. executeOrder
and alert functions (alertEmail, alertMessage, alertSound
) are the heart of the application.
'"`UNIQ--toggledisplay-00000008-QINU`"'
Step #13. Create an object of StrategyCallback
'"`UNIQ--toggledisplay-00000009-QINU`"'
Step #14. Implement IndicatorTickSource
Strategy always need two “tick” streams for “bid” and “ask” prices. '"`UNIQ--toggledisplay-0000000A-QINU`"'
Step #15. Implement IndicatorBarSource
Strategy always uses two tick streams, but strategy may also need “bar” stream. You need to implement IndicatorBarSource in case the strategy can use time frame other than “tick” '"`UNIQ--toggledisplay-0000000B-QINU`"'
Step #16. Get and Keep Price Streams
Class HistoryMgr
is used to prepare price streams: “bid” and “ask” sources for the strategy, as well as streams for strategy’s getHistory
requests. History manager keeps strategy instance with a list of price streams for this instance in a dictionary. Class Ticket
is used to keep all information about price stream.
History manager has function PrepareTicks
to create “bid” and “ask” sources for strategy. First it gets historic prices. It this case application uses synchronous call because prices have to be filled in order to create strategy instance. There could be new ticks coming from the moment of the GetPriceHistory
call to the moment of getting the result with 300 ticks. Function GetPendingEvents
of the trading desk is used to get new ticks. Function MergeTicksHistWithTicksBuffer
is used to merge historic and new ticks.
History manager has function GetPriceHistoryAsync
for getHistory
request from strategy. One of the arguments is a cookie
from the strategy to be used in notifyFinished
. GetPriceHistoryAsync
function creates an empty stream, and sends an asynchronous call to get historic prices. Application does not wait for prices to be filled. Instead it gets request ID for the history request (it would be used in event OnPriceHistoryCompleted
). The empty stream is attached to the instance of a strategy together with supporting information (price history request ID, cookie
for notifyFinished
). The stream would be kept with a flag PriceHistoryCompleted
as “false” until prices would be filled.
Function ProcessPendingEvents
checks pending events, and in case there were new prices (“new offer” events), new ticks are added for all completed streams (ticks are kept in a buffer for uncompleted streams).
Function ProcessTick
adds new tick for all corresponding tickets (the tick should be stored in the tick buffer in case stream is not filled yet).
Function AddTick2Stream
adds a tick to tick stream or bar stream.
Function Attach2Instance
attaches price stream to strategy instance to keep them together in a dictionary.
'"`UNIQ--toggledisplay-0000000C-QINU`"'
Step #17. Prepare Tick Sources for the Strategy
Enable pending events for the trading desk (it will allow you to store and later extract coming ticks). It is important to do it before the call to get last 300 ticks.
Ask HistoryMgr
class to prepare ticks for you. You need the tick history up to “now” (use 0 as date “from” and date “to”, and “t1” as time frame). History manager would do the work of merging “historic” ticks and “new” ticks.
'"`UNIQ--toggledisplay-0000000D-QINU`"'
Step #18. Keep Information about Orders
Class Order2Go
keeps information about the trading orders requested by the strategy. In the example below the information is kept in a dictionary where strategy instance is a key, and the list with information about corresponding orders is a value. A helper class OrderInfo
is used to keep information about an order (request ID, strategy’s cookie
, and time of request.
Class Order2Go
is also used by MyHost
to get trading day offset, trading week offset, trading properties, and for price history helper.
'"`UNIQ--toggledisplay-0000000E-QINU`"'
Step #19. Create Strategy Instance
Create a strategy instance, using two “tick” streams, strategy callback function, and parameters. '"`UNIQ--toggledisplay-0000000F-QINU`"'
Step #20. Attach "Bid" and "Ask" Streams to History Manager
History manager (HistoryMgr
) keeps all streams for the strategy instance. “Bid” and “ask” tick streams are special, because they were created before the strategy instance was born. That’s that is why you have to attach them to strategy instance right after creating a strategy instance with those streams.
'"`UNIQ--toggledisplay-00000010-QINU`"'
Step #21. Watch for New Prices
Get into the loop. Program will ask history manager to process pending events (it is done by function ProcessPendingEvents
), and in case there are new prices, all price streams associated with the strategy instance would get new ticks (bars), and the strategy instance would be updated.
'"`UNIQ--toggledisplay-00000011-QINU`"'
Step #22. Watch for Price History Events
Each time when event OnPriceHistoryCompleted
happens, check the dictionary in history manager, find a stream for the price history request, fill it with the prices you got, add new ticks stored in the buffer for the stream (if any), mark stream as completed, and call notifyFinished
for the strategy instance (function FxCore_OnPriceHistoryCompleted
).
Notify strategy instance in case OnPriceHistoryFailed
happens as well (function FxCore_OnPriceHistoryFailed
).
Step #23. Watch for Request Events
If the strategy is allowed to trade, notify strategy instance when events OnRequestCompleted or OnRequestFailed happen (functions FXCore_OnRequestCompleted
and FXCore_OnRequestFailed
). Check Order2Go
dictionary, find information about the order for specific request, get a cookie for the strategy, and call notifyFinished for the strategy instance.
Sample Project
You can download sample project here:
File:ExecuteStrategyNET.zip.
To run the program use these arguments: username, password, instrument (optional), and time frame (optional). The default instrument in "EUR/USD", and default time frame is "m1" (one minute).
This Article in Other Languages
Language: | English • español • français • русский • 中文 • 中文(繁體) |
---|