1. 首页
  2. 易语言 - EasyLanguage
  3. 用OrderTickets 和DataProviders下单交易 EasyLanguage-based Trading with OrderTickets and DataProviders
  1. 首页
  2. 策略回测、分析和自动交易 - Strategy Backtesting, Analysis, Trading & Automation
  3. 用OrderTickets 和DataProviders下单交易 EasyLanguage-based Trading with OrderTickets and DataProviders

用OrderTickets 和DataProviders下单交易 EasyLanguage-based Trading with OrderTickets and DataProviders

本文讲述如何用 OrderTickets 对象下单并且用 DataProvider 监测实际的交易情况。

Introduction

Developing an indicator to perform trading and trade management will require the use of OrderTickets (OTs) to place orders and DataProviders (DPs) to monitor the actual trading.  
These will require using object-oriented-programming (OOP) techniques, including an event-driven programming structure. Although the use of OTs and DPs give the developer significantly greater flexibility and control, this comes at the cost of significantly larger studes with greater complexity. There is additional fuctionality that having a working knowledge of will greatly benefit the study development. This incudes such things as collections, WinForms and often file/directory I/O and XML. 

There is no one specific template that will work with all trading algorithms. One must choose the types of OTs to be used, when they are used and how specific DPs can 
be used to reach the desired objective. 

Differences from Strategies
If you have been developing strategies there are some key differences in how one must think about how trading with OrderTickets and DataProviders works. 

Code Execution
Most strategies are designed to execute on bar close, although if intrabar order generation (IOG) is enabled the strategy code executes on every tick. 

Indicators normally default to execute on every data tick, although there is an option to only execute on bar close. 

You need to take this difference into consideration.  

Order Submission
A strategy may only submit an order on a data tick. It may not submit an order from an event handler, such as a timer elapsed or a GlobalDictionary ItemAdded or ItemChanged events.  

An indicator may submit an OrderTicket at any time, including from an event handler. Zero or more Orders may result from the sending of an OrderTicket. Once the OrderTicket has been sent, all management of the trade must be accomplished my managing the Orders. 

Order Lifetime
A strategy must continue to send in an order on every execution of the strategy for that order to remain in place. Once an order is not resent, the strategy engine will initiate a cancel of that order. 

When an indicator sends an OrderTicket, it only needs to do this once. Once the OrderTicket is received the generated Orders are resident on the TradeStation servers and will remain there until some terminal state is reached, such as FILLED, EXPIRED or CANCELED.  

While the strategy engine will initiate an order cancel once that order is no longer sent in, with Orders resulting from OrderTickets the code must explicitly cancel Orders. 

Strategy orders are day orders. OrderTicket generated orders may have their duration specified, such as DAY or GTC. 

Code Structure
A strategy is typically designed to execute on bar close or every data tick. The code starts executing at the first line of body code (code not in an method or once block) and proceeds through the lines of code to the last line. 

An indicator’s code will be mostly methods and event handlers for various DataProviders and other OOP classes, with few lines of body code. 

Trading Information
The strategy has acces to a large number of reserved words to allow the code to easily determine the state of the trade and prior trades. These are words like “MarketPosition”, “BarsSinceEntry”, “SetProfitTarget”, etc. Essentially any of the reserved words in the Strategy Automation, Strategy Orders, Strategy Performance and Strategy Position groups under the EasyLanguage.ell section of the TDE Dictionary.  

The code of the indicator must obtain this information from various DataProviders and classes and establish variables and collections to retain this information. A large portion of the code for an trading indicator will be associated with this aspect.  

Backtesting
There is no built-in functionality to perform backtesting with OrderTickets and DataProviders. One should generally have a strategy to perform backtesting and use the trading indicator solely for automation. 

Sequence Management
With OrderTickets and Orders much of the sequencing of operations requires initiating a process and then waiting for some event to occur in order to initiate the next step. This asynchronous structure is very different from the typical synchronous nature of strategies. 

Updating an Order
In a strategy an order is effectively updated by changing one or more properties of the reserved word that sends the order. The strategy assumes the old order was canceled (and not filled) and submits the new order.  

With Orders the code must build a ReplaceTicket and use the Order.Replace method to send in the replace request, and then wait for an Order updated event for that Order with a Order State/DetailState = Recieved/Received or Order State/StateDetail = Recieved/ChangeRequestRejected, and act accordingly. It is best to supply all the properties of a ReplaceTicket.  

Overall Design

Logging

When developing a complex large trading indicator, logging to a file should be one of the first major subsystems to include in the code. The logging should be verbose and as well structured as possible. This log will be a great benefit during the debugging and execution phases for the project. With a real-time system things will happen quickly and there is no stopping things for a bit to examine things. The log file contents should contain a complete record of all actions taken by the software. This would include: 

• DateTime stamping every line 
• Logging all input values 
• Logging any chart or RadarScreen parameters, such as bartype, barinterval, symbol, etc. 
• Logging all OrderTickets 
• Logging all Order events 
• Logging data prices at key action points 
• Logging all critial calcuated values at key action points 
• Logging any performance metrics  

You may want each execution to have its own log file, timestamped to the second, or to have a new log file for each day or session. 

Factors

The overall design of indicator code to perform trading using OrderTickets and DataProviders depends upon a number of factors. Often the design must make compromises between the different factors. One must understand the different OrderTicket structures – simple, OSO, OCO, Bracket as well as Replace tickets and approaches for canceling orders or closing positions. 

There is no single template for an OOEL-based trading study. The final design must reflect the various aspects of the trading algorithm.  

Code Execution

Unlike a strategy, the orders resulting from OrderTickets are on the TradeStation servers and the indicator does not need to be running for the trade to complete. The TradeStation servers will handle them accordingly. 

However, there are situations that would require the indicator to be executing, usually around situations in which the orders need to be modified based upon price activity or the passing of time.  

A set of orders may be created that supports trailing stops, end-of-day exits, and stop adjustment based upon targets being hit, etc. 

The compromise is often whether one wants all the orders to reside on the TradeStation servers versus the need to update these orders based upon market activity. 

Depending upon the reliability of one’s Internet connection the need to have everything resident on the server may or may or may not be critical. 

Note that regardless of the code execution approach taken, one should be monitoring the trading system as it involves many parts, any of which could fail for reasons beyond one’s control.

Multiple Trading Algorithms on same Symbol

If there can be multiple independent trading systems trading the same symbol, then the design cannot rely on a PositionsProvider as heavily as when there is only one system trading. In addition the trading algorithm will need to keep track of every OrderID in order to cleanly identify orders from this algorithm versus orders for the same symbol resulting from a different algorithm. 

A mechanism will most likely be needed at startup to ensure that the existing position and the perceived position of the algorithm are correct, and if not how to reconcile. 

Number of orders in exit bracket

A BracketOrderTicket only supports two orders, namely a target and a protect (stop). 

An OCOOrderTicket can support one or more orders. This can be useful if one wants an end-of-day exit or a trailing stop in addition to a fixed stop. 

Canceling Orders

To cancel an Order, the Cancel method of the Order object may be used. If the Order can be canceled then it will proceed through the CancelingPending state to the Canceled State. Note that there may not be an Order updated event for the CancelPending state. If the Order being canceled has dependent Orders, such as the secondary Orders resulting from an OSOOrderTicket, the dependent Orders will be canceled. 

If the Orders in a Bracket or OCO group are active and are to be canceled, each Order must be individually canceled. 

The OrderTicket class has several static methods that allow canceling of all orders for an account and symbol (OrderTicket.CancelAllOrders) and one that allows canceling of a specific Order given its OrderID (OrderTicket.CancelOrder). 

Entry Partial Fill Handling

If one is trading more than a quantity = 1, then there is the possibility of partial fills with limit orders.  

If an OSOOrderTicket is utilized, then the orders resulting from the secondary order tickets are not made active until then entire entry quantity has been filled. If the entry order is only partially filled and the price moves away from the entry toward the exits, these exits are not active and therefore will not be filled, potentially resulting in missed profits or excessive losses. 

If a simple OrderTicket is used for entry, then as it is partially filled, OCOOrderTickets or BracketOrderTickets can be used to implement the target and/or stops for each partial fill. This avoids the issue of not having active exit brackets, but does potentially result in more orders for handling exits. The exposure with this approach is the very small time window in which there is a position without any exit bracket.  

Exit Partial Fill Handling

It is possible that an exit order (target or stop) may only be partially filled and then the price move toward the other exit order.  

If the exit orders were submitted using an OCOOrderTicket, then it is possible that the exit orders will be cancelled upon a partial fill, leaving a position that has no exit orders. 

If the exit orders were submitted using a BracketOrderTicket, then the bracket exit orders will not be canceled and the quantity of the opposite order to the one partially filled will have its quantity adjusted to the remaining quantity. 

Partial Fill

If one is trading a quantity greater than one with a limit order, then a partial fill is possible. If one is trading futures or options and the quantity is not large, then one can avoid the partial fill issue for both entries and exits by only submitting orders with quantity one.  

If one wants to trade more than one contract, one can simply construct order tickets for quantity one and submit them multiple times. This totally avoids the partial fill issue. It does however leave one with the task of potentially canceling unfilled entry orders once the market conditions have changed such that an entry is no longer desired, but this is a typical requirement in any case.  

Activation and Deactivation Rules

Are there any orders that must be activated or deactivated based upon the time-of-day for the current day? Note that time-of-day activation can only be scheduled for the trading session when the order tickets are submitted. 

Are there any price-based activation requirements? 

Note that there is no support for price-based deactivation rules. 

Scaling In

If scaling-in is based solely on price action and the quantities are predetermined, then an OSO OT with a Price Activation Rule can be sent in. The exit order structure would need to conform to an appropriate structure. 

A scale-in based upon time can be handled with time activation rules. This is better than a timer waiting to submit a new order. 

A scale-in based upon other criteria would require specific code to detect and submit additional orders. 

Scaling Out

If scaling-out is price-based and with fixed quantities, the structure of the exit orders associated with the entry orders can handle everything.  

If scaling-out quantity or price is determined by market action, then it would need to be handled by executing code. 

A scale-out based upon time can be handled with time activation rules. This is better than a timer waiting to submit a new order. 

A scale-out based upon other criteria would require specific code to detect and submit additional orders. 

Unlike a strategy, there is no need to match exit orders to entry orders. 

Duration

Will all positions be entered and exited in the same day, or will a position be held overnight or for a longer period. 

Session

If orders are to be placed outside the normal session for stocks, then additional order durations may be needed and the actual order types allowed may be restricted. 

Additional Symbols or Intervals

Is price or other data needed from other symbols as part of the trading process, or is data needed from intervals different from the base interval? If so, additional data streams or synthetic bars may need to be constructed, or one or more PriceSeriesProviders may be needed. 

Data Structure for Orders

If the trading algorithm ever needs to cancel an existing order or to change an existing order (using a ReplaceTicket), then it is necessary to keep track of all the orders generated by the OrderTickets. 

To effectively maintain the information about Orders, OrderTickets, etc. you will want to become proficient in the use of the EasyLanguage collections, and specifically the Vector and Dictionary and potentially the GlobalDictionary and AppStorage. 

A good starting point is to use the overload of the order ticket send method that includes the Boolean parameter set to true. The send method returns an Orders object, which is a collection of all the orders resulting from the OrderTicket. If an OrdersProvider is used, any updated events will return the same order objects as returned by the send method. 

The approach of capturing the order objects resulting from order tickets sent in by this indicator instance is necessary if there are multiple trading indicators trading the same symbol. Otherwise the code would not be able to distinguish between orders for itself and other trading activity. Using the Send(true) overload for an OrderTicket returns the Orders collection. 

These order objects can be used to submit cancel requests or replace requests.  

The data structure chosen may integrate with the approach to Restart Recovery. Since collections and objects cannot be saved natively to a file, one may need to convert from the collection contents to string values stored in a file or an XML document. This would also require storing ID information (such as OrderID) in the file, and then retrieving the actual objects (such as Orders) from the appropriate data provider. 

Restart Recovery

One should always anticipate that there may be some situation that results in the indicator stopping (system crash, power failure, etc.).  

If there is only one source of trades for a symbol (namely the indicator) then through judicious use of the OrdersProvider and PositionsProvider the indicator can determine its actual position and state and obtain the orders needed for canceling or replacing.  

Another approach is to record information in either AppStorage or a file that can be read to determine the state of the indicator upon starting. The PositionsProvider and OrdersProvider may still need to be used to handle position and order events that occurred while the indicator was not running. 

Exchange Implementation, Handling and Restrictions

It must be recognized that different exchanges have different and sometimes unique ways in which specific order types are handled or special situations are handled. 

Specific areas include: 
• CME price banding on limit orders 
• CME Stop order to Limit auto conversion 
• Order resubmission on new sessions 

Application

A trading algorithm implemented in an indicator may be used in a chart with a single symbol, or a RadarScreen with multiple symbols. A TradingApp is a Window-based standalone application that is not associated with a chart nor RadarScreen. 

Complex Systems

A trading system may require multiple applications and studies. These studies and applications may be: 
• Indicators 
• TradingApps 
• Scanner 
• RadarScreen 
These studies may: 
• Identify trading opportunities by symbol 
• Perform actual trading 
• Handle risk management and asset allocation 

The GlobalDictionary and Files are two mechanisms for communicating between these. 

OrderTickets

Introduction

An OrderTicket is sent to the TradeStation Trade servers and can result in one or more Orders being created.  

The Send method of an order ticket is used to send an OrderTicket. There are two overloads for a Send method: 

Send() – The return value is a single order object. 

Send(true) – The return value is an OrderCollection containing 1 or more Order objects. 

An OrdersProvider can be used to monitor the state of each Order resulting from an OrderTicket. 

The choice of what approach to use with OrderTickets depends upon what security is being traded, the type of order used for the entry, and whether the orders need updating during a trade. Once major advantage of using OrderTickets is that once sent by the client and received by the TradeStation servers, the orders remain on the TradeStation servers until canceled (by either the study or if the order duration is hit), even if the client platform is no longer connected to TradeStation.  

OrderTicket Types

OrderTicket

• Results in a single order 
• An OrderTicket may have an activation time-of-day and/or a deactivation time-of-day associated with it. Note that these times are within the day (session) the order was submitted; they cannot be for a time-of-day of a future day or session. 
• Order tickets may have price activations rules associated with it. The price may be for the specific symbol or for another symbol. For example code might activate a rule for trading an option based upon the price of the underlying symbol reaching a specific price.  

OSOOrderTicket

• Used to submit a primary order and optionally zero or more secondary OrderTickets 
• The Primary OrderTicket is normally a simple OrderTicket to enter a position 
• Each secondary OrderTicket is typically an OCOOrderTicket or a BracketOrderTicket, although simple OrderTickets may be secondary orders 
• All secondary tickets are held in a QUEUED state until the entry order is completely filled. In the QUEUED state they are not active. 

OCOOrderTicket

• A collection of orders that will all be put in the same OCO Group. 
• There is no practical limit to the number of order tickets that may be placed in an OCOOrderTicket. 
• If any order in the OCO group is filled, all the other orders are canceled. 
• If an order in the OCO group is partially filled, all the orders in the group are canceled.  

BracketOrderTicket

• An order ticket that can generate a target order and/or a stop order.  
• No other additional orders may be placed in the bracket OCO group. 
• If any order in the BOT OCO group is filled, all the other orders are canceled. 
• If an order in the BOT OCO group is partially filled, the quantity of the other order in the group is automatically adjusted to reflect the remaining quantity to be filled.  
• The actual target (Target) and stop orders (Protection) are OSO orders with no secondary orders, although code can add secondary orders to the target and/or stop orders. 
• Typically one can set all the desired properties without using the Target or Protection OSOOrderTicket properties, but these may be needed if some more advanced functionality  
is desired, such as establishing a trailing stop. 

Activation and Deactivation Rules
The ActivationRules property of the OrderTicket contains properties for setting time-based and price-based activation rules. 

Time-Based
An OrderTicket may have an activation time-of-day and/or a deactivation time-of-day associated with it. This rule will apply to the Order generated by the OrderTicket. Note that these times are within the day (session) the order was submitted; they cannot be for a time-of-day of a future day or session. 

The following code demonstrates adding a time-based activation rule to the OT OrderTicket being constructed. The activation time is specified by a DateTime object DTEOD. 


select all

The following code demonstrates adding a time-based deactivation rule to the OT OrderTicket being constructed. The deactivation time will be set the the requested number of seconds after the current time. 


select all

Price-Based
An OrderTicket may have an activation rule based upon the price of one or more securities (the traded security or another security) to activate the Order. There is no price-based deactivation rule. One or more PriceActivationRule objects may be created and added to the collection of Rules in the OrderTicket ActivationRules object. 

The following code demonstrates the addition of a Price-based activation rule for the current symbol. Multiple PriceActivationRules may be added to an OrderTicket. 


select all

Order Ticket Properties Not Applicable to the US Markets
The OrderTicket has a number of properties that do not apply to the US security markets. You should not set any of these properties. They are: 
• ActionEx 
• ExtendedProperties 
• TriggerPrice 

Order Ticket Properties Only Applicable to POV-ALGO, VWAP-ALGO and TWAP-ALGO Routing
The OrderTicket has a number of properties that only apply to specific routing codes. You should not set any of these properties if one of these routings is not used. They are: 
• EndTime 
• ExecutionStyle 
• MaxPercentVolume 
• MinPercentVolume 
• StartTime 

ReplaceTicket
A replace ticket can be used to change some properties of an existing order. Not every property of an existing order can be updated and not every combination of updates is valid, even if the ReplaceTicket would allow you to set the properties. A good rule-of-thumb is if the change is permitted by the Order Bar then the updates are valid from EasyLanguage. 

One should endeavor to supply values for all the properties of a replace ticket, not just the ones that are to be updated. Failure to do so may result in the ReplaceTicket actually not updating the order and there being no events to indicate the order was not updated. Note that over time additional properties have been added to the ReplaceTicket and one could expect more to be added in the future. 

Note that once an Order is active, if the limit or stop price were determined by a style of ParentPlus, the order limit price has been calculated and the PriceStyle is set to None and PriceOffset is set to 0. A ReplaceTicket must submit a price change as an absolute price with PriceStyle = None and PriceOffset = 0. 

The return value from the Replace method should be checked. One or two order updated events should result from the replace actually occurring. One event reports on the current state of the Order that will be replaced. The second event indicates that the replace operation occurred and shows the new Order information. 

• Used to update an existing order. 
• Only certain properties of an order may be updated. 

Some Typical OrderTicket Scenarios

Market Entry – Any Security TYpe

Entry and Exit
• Any security type 
• Market Entry 
• Fixed Target(s) 
• Stop (fixed or trailing) 

Implementation
• OSO entry order with full quantity 
• BOT for each target with target quantity 

Discussion
• Entry should always fill so no entry partial fill issue 
• BOT handles exit partial fills and opposite side size adjustment 
• All orders on and handled by TS server 

Limit Entry – Any Security Type

Entry and Exit
• Any security type 
• Limit Entry 
• Fixed Target(s) 
• Stop (fixed and/or trailing) 

Implementation
• OT for entry 
• Send BOT for each partial fill, adjusting for quantities for each target 

Discussion
• Entry may fill 
• BOT handles exit partial fills and opposite side size adjustment IF ACTIVATED 
• All orders on and handled by TS server 

Market Entry – Futures

Entry and Exit
• Futures 
• Market Entry 
• Fixed Target(s) 
• Stop(s) (fixed and/or trailing) 

Implementation
• OSO with entry order with full quantity 
• As many OCOs with quantity =1 for each target/stop need to match the entry quantity 
• Each OCO contains target, stop and an optional end-of-day order (which is a market order with a time activation)  

Discussion
• Entry should always fill so no entry partial fill issue (exit orders not activated until entry order totally filled) 
• OCOs with quantity=1 avoid any exit partial fill issue 
• Any order in OCO group filled cancels the others 
• All orders on and handled by TS server 

Limit Entry – Futures

Entry and Exit
• Futures 
• Limit Entry 
• Fixed Target(s) 
• Stop(s) (fixed or trailing) 
• Optional EOD exit 

Implementation
• Multiple OSO order tickets 
• OSO with entry for quantity 1 
• OCOs with quantity = 1 
• Each OCO contains target, stop(s) and optionally an EOD (which is a market order with a time activation) 

Discussion
• Entry should always fill so no entry partial fill issue (exit orders not activated until entry order totally filled) 
• OCOs with quantity=1 avoid any exit partial fill issue 
• Any order in OCO group filled cancels the others 
• All orders on and handled by TS server 

DataProviders

You should review the general information about DataProviders in the forum topic Data Provider Best Practices 

There are a number of DataProviders (DPs) contained in the tsdata.trading namespace what are useful. This topic will not discuss the DataProviders from the tsdata.marketdata namespace as these 
are not directly involved with actual trading. 

The following are the typical trading-related DPs that are of use: 
AccountsProvider – The AP provides account beginning-of-date and real-time account values 
SymbolAttributesProvider – The SAP provides information about the symbol 
PositionsProvider – The PP provides information about the current posistion, if any, for symbols in accounts 
OrdersProvider – The OP providers information about orders and their state changes for symbols in accounts. 

You should review each property of the DataProviders and the objects they return. In addition you should review the data available in the EventArgs for each StateChanged and Updated events. 

Note that since a study can only process one event at a time from DataProviders and any trading event can result in events for the AP, PP and OP and the order in which those events occur may vary, this must be taken into consideration when using such events to make trading decsions. 

AccountsProvider
The accounts provider (AP) exposes those accounts available with the current TradeStation logon. Each account has a number of properties that may be useful for monitoring buying power and account equity. 

Note that the AccountsProvider can generate a large number of events as a number of the properties change with every change in the price of any security for which there is a position. The latest property values can always be retrieved from an Account object without having the updated event enabled. 

SymbolAttributsProvider
The SymbolAttributesProvider (SAP) has numerous properties for a symbol. SAPs can be useful if the study needs to reference properties of multiple symbols. 

Two properties of use for making a trading study independent of the user’s time zone are GMTExchangeOffset and GMTLocalOffset. 

PositionsProvider
The PositionsProvider returns a Position object for each position currently held for the specified accounts and symbols. There can only be one position for a specific symbol in an account. 

Note that the PP and the OP both can be used to monitor the position. However since events are only processed one at a time and either the PP or OP may fire before the other, one generally should use one or the other to monitor the position. Using both independently to make trading decisions may result in the “two watch” issue – one never knows the correct time since the two watches are different. If both are used it is better to make trading decisions when both are checked and agree. 

The positions provider Position object makes some useful data available (such as the AveragePrice and Profit & Loss information) but it does not give you the position exit price. For this information you will need to resort to analyzing the Orders involved in the position. So in most situations the code will need to rely on both the PositionsProvider and the OrdersProvider to determine the complete set of information about a position 

OrdersProvider
The OrdersProvider (OP) can be one of the most useful data providers. It gives access to the orders that have been placed for the specified filters (accounts, orders, symbols, states, from, to). 

If one has multiple trading studies trading the same symbol, then tracking all the specific orders generated by the study and only utilizing these orders is one way to avoid having two studies interfere with each other’s trading.  
Note that the OrdersProvider retrieves orders with an EnteredTime within the “from-to” date range.  

Realtime
With the OP.RealTime = true, the OP can provide events whenever the state of an order is changed. This allows real time monitoring of the status of orders. A study doing trading would typically have a RealTime OP. A RealTime OP would typically contain in its Order collection any orders entered during the current session or still active (in a non-terminal state) but entered during a prior session. 

The Order objects in the RealTime OP Order collection are the same objects that would be returned by an updated event. 

Historic
With the OP.RealTime = false, historic orders for a date range and the applicable filters can be obtained. A study would not normally need a non-RealTime OP unless there was a need to obtain data from orders entered and which reached a terminal state during a prior session. 

Note that the Order objects available from a non-RealTime OrdersProvider are never updated, and for non-terminal Orders the object would NOT be the same as the object returned for that Order from the RealTime OrdersProvider 

Filters
There are a number of properties that a study may specify to filter the orders received.  

The OP.Accounts can by used to specify a list of accounts for which orders are to retrieved. Left blank indicates that Orders from all accounts are to be retrieved. 

The OP.Symbols property can be used to restrict the Orders retrieved to those of the symbol(s) specified. 

The OP.Orders property can be used to restrict the Orders retrieved to those in the list of OrderIDs. 

The OP.States property can be used to restrict the Orders retrieved to those with a specific state. It is recommended that the “States” filter not be used but rather the code filter the orders.  

The OP.From and OP.To DateTime properties can be used to retrieve orders between the two dates. The time portion of the DateTime is ignored. 

Order States
The following chart shows the various states an order my go through. Note that any non-terminal state may not have an event raised if a subsequent state is almost immediate. 

Updated Event
An updated event may be established for the OrdersProvider, but it may also be established for an Order. Since an Order must already exist before an updated event can be established for it, it is likely that the Sending and possibly Sent state events would not fire because they may have already occurred before the updated event was linked up. 

One advantage to using the updated event on Order objects is that the study can then receive only the events for the Orders in generated rather than for all Orders. This would be an advantage in there were two studies trading the same symbol in the same account. 

The Order updated events will be the only way for the code to determine if an order is rejected, an Order was not sent to the Trade Servers, that an Order ReplaceTicket was processed or rejected or an Order that was requested to be canceled was actually canceled. Therefore the code will heavily depend upon the OrdersProvider and its updated events. 

Trade History
Often one wants to recreate the trade history for a symbol. The OrdersProvider in non-RealTime mode is the key data provider for building a history of trades. With it code can obtain all the historical orders in their final state (filled, canceled, etc.). One can then iterate (from oldest to latest) through all these orders to obtain the “avgfillprice” and “filledquantity” and “action” (buy, sell, etc.) from which a P&L can be calculated.  

If you only do day trades and the symbol is flat at the start and end of the day then just select the from and to dates to be the day of interest and accumulate the P&L from the orders.  

If one holds positions overnight or is possibly in a current position, then the issue is a bit more complicated. First use the PositionsProvider to find the current position, and then one must take a guess at how far back in history one wants to go. Then load the OrdersProvider with the “from” and “to” properties set to the appropriate dates and work backwards (current to oldest) through the orders to reconstruct positions, taking the current position into account. Note that the oldest trade being constructed may not be complete if the position actually started before the “from” date. 

Receiving Orders Extra Times
There are certain situation that arise, typically when there has been a disconnection/reconnection occurrence, after which the RealTime OrdersProvider may receive again an updated event for all the orders previously received. This event will reflect the latest state of the orders. Depending upon how you have programmed the trading algorithm, the code must be able to avoid misinterpreting these events and taking actions that were correct the first time such an event was received for the order but would be incorrect on a subsequent event. 

One approach to handling this situation is to record the OrderID and latest state for every order, including any orders loaded when the data provider reaches the loaded state as well as any orders received through the updated event. When a new event occurs for an OrderID, its state would be checked against the last recorded state to determine if this event should be ignored or processed. A dictionary (with the OrderID as the key) and the value as a dictionary containing whatever information needed (like state, EnteredTime, etc.) is a good approach. 

Note that during the early morning hours TradeStation performs maintenance and backup operations on its servers which may result in one or more disconnection-reconnection sequences for both the data and trade servers. 

Other Important Classes

The details of the classes referenced below will not be included in this topic. Only their potential use is highlighted. 

Collection Classes

Vectors and Dictionaries will be very useful to hold the “bookkeeping” data structures for tracking Trades, Positions, OrderTickets, Orders, etc. 

StreamWriter

The StreamWriter will be the primary mechanism for writing the log files generated by the study. 

StreamReader

The StreamReader may be useful if the study needs to read in any configuration information or data needed for trading from a file. 

ConnectionStatus

This class allows the determining and monitoring of the market data and trading conection states. Recording disconnections and connections will be useful. 

Drawing Object Classes

Various DrawingObjects may be useful in annotating a chart to highlight key events or actions or conditions. 

ChartingHost

The ChartingHost is useful in determining the color of a chart. It can also be used to allow hot-key detection from the chart to allow user input. 

GlobalDictionary

Useful if communication is required to other studies or applications. For example, if all capital allocation and/or risk management is to be handled by a separate TradingApp, the GlobalDictionary would be the best communications mechanism. 

XML Classes

Configuration and certain types of logs my be best handled via XMLDocuments and their string-serialized representation to a file. An XML document is essentially an heirarchical database, so it could be used to contain a record of positions, with the OrderTickets and generated Orders being elements under a Position. 

Windows Forms Classes

One or more forms associated with the trading indictor or for use with a TradingApp can give very good visual information as well as allow for interaction with the trading, such as adjusting trading parameters, without the need to update inputs of the studies. 

Data Structures

Depending upon the details of the trading rules, the study may need to keep detailed information about the OrderTickets, Orders and Positions. Vectors and Dictionaries are an excellent tool for this. Among the basic collections that may be helpful are: 

BarsInfo – This is a vector that contains BarInfo dictionaries. Each BarInfo dictionary corresponds to a single bar in your data stream. The BarInfo dictionary would typically contain information about the bar at bar close time. This would be the obvious data such as BarDateTime Barnumber, Open, High, Low, Close, Volume, etc. But you may also include values for functions such as Average, RSI, etc. Use of the BarsInfo vector can avoid using back-references. Typically the current or latest bar is inserted at index 0 so that indexing into the vector is essentially the same as back-reference values. 

Trades – This vector contains Trade dictionaries. The dictionary contains information about the entry and exit from the trade plus profit and loss and any other information that may be needed. For example if the trading algorighm utilizes trading day target and/or loss limits, having the trades collection can facilitate the calculation of P&L over any period. 

Orders – Given that the OrdersProvider can republish Orders that were already in a terminal state, a mechanism may be required to identify orders from an updated event that are just repubished so that they can be ignored in terms of responding to them in the trading algorithm. 

Easylanguage Code Samples

Useful Functions

The following functions are extremely useful for generating log files. Each function formats the values in a specific object type as a string. 

ELCFormatAccount – Formats an account from an AccountsProvider. 
ELCFormatBarType – Formats a bar type as a string. 
ELCFormatBarTypeAbbr – Formats a bar type as a string abbreviation 
ELCFormatDrawingObject – Formats a DrawingObject. 
ELCFormatGenerationApplication – Used by ELCFormatOrder. 
ELCFormatOptionSecurity – Formats an OptionSecurity from the OptionChainProvider. 
ELCFormatOrder – Formats an Order. 
ELCFormatOrderTicket – Formats a simple OrderTicket. 
ELCFormatPartialFills – Format an Order’s PartialFillInfo object. 
ELCFormatPosition – Formats a position. 
ELCFormatPriceFraction – Formats a price using fractions rather than decimals. 
ELCFormatReplaceTicket – Formats a ReplaceTicket. 
ELCFormatSAP – Formats a SymbolAttributesProvider. 
ELCFormatTimeSpan – Formats a TimeSpan. 

更新于 2020年6月5日

这篇文章对您有帮助吗?

相关的话题

留言评论