The Local Order Manager has been designed to replace the internal NinjaTrader order management functions. It is based upon Unmanaged Order Management function. The goal is to create complex and flexible features that can easily be re-used, freeing the programmer of the strategy to focus upon the intended strategy and not getting bogged down with coding and debugging.
This Wiki will discuss the use and application of the Local Order Manager. A separate user manual will cover all the functions available. This Wiki may not cover all function and their usage. Please use the Local Order Manager forum for specific questions.
Legal Stuff: Do not distribute this code compiled or in source format beyond the Elite section of Big Mike Trading. You may not claim this as your own. You may not sell or in any way redistribute this code without prior authorization. This project is designed to be a way to collect the knowledge of the nexusfi.com (formerly BMT) community to leverage and improve over time. The hope is the work will help contribute to highly profitable Automated Strategies based upon the Entry/Exit/order management provided by this class. Use this at your own risk as it has not be fully debugged with your application. Debug and test before you assume risk of live trading with any strategy using the local order manager.
BarsInProgress - Usually equals 0, but NT will change this value upon calling "OnBarUpdate()" when processing a different bar from a different dataseries/instrument
LOM - Abbreviation for the Local Order Manager
NT - NinjaTrader
Position Number - A unique "slot" or Order position maintained by the strategy
The basic concept of the local order manager revolves around "Position Numbers". Position Numbers are simply the "Slot" or numeric reference to a unique order for your strategy. Many strategies will only use 1 Order slot. The first slot would be "0" and currently 10 positions are supported so the range will extend to "9".
Although multiple Position Numbers are allowed within the LOM, the strategy still cannot violate any rules of the broker. In most cases, you will not be able to maintain a LONG position 0 and a SHORT position 1 as the broker is likely to exit the LONG position as the strategy enters the SHORT position.
The "Initialize()" function is used to setup the basic connections of the NinjaTrader Strategy to the Local Order Manager. This is accomplished by creating a global variable for you strategy to access the Local Order Manager (LOM). This is accomplished by adding a line such as this in your variables section of you strategy:
This creates the variable m_OrderManager as access for the Local Order Manager (LOM).
In your "Initialize()" function initialize the variable with a new instance:
The class requires a "Strategy" and "this" is passed to send the current strategy as this parameter. The following is the "BarsInProgress". This value will normally be "0" and is used to tell LOM what dataseries/instrument to send in orders against. 0 is the primary dataseries/instrument (generally the main chart the strategy is attached).
The following functions should be considered as part of the Initialize() function.
For debugging of a strategy or visualization of SL/PT use the "SetDebugLevels(int m_LogOutput, int m_ChartOutput, bool m_TraceOrders, int m_StreamOutput)" function.
m_ChartOutput: Graphic output on chart for Order detail, SL, PT, etc
m_TraceOrders: true/false for producing order tracing output
m_StreamOutput: Output to a data file (currently not implemented)
The next function can be used to disable the LOM status box. "SetAutoSLPTTicks(int m_StopLoss, int m_ProfitTarget,int m_PositionNumber)" function setups the default SL, PT for each position number in the strategy. These orders will be placed upon any entry LONG/SHORT in ticks for each Position Number. This can be different for each position in the strategy. Set the SL or PT to 0 no order should be placed to cover.
The following code fragment must be added to the strategy for the LOM to function. Additional features can be added if required in these overrides, but should follow the LOM function call:
These functions are required to give LOM access to Order Updates as well as TICK based data. Without these the LOM will not process orders properly. This would be the first debugging step with any problem with a strategy based upon this order class.
This section will cover entering a LONG position. All of these functions have a Mirror by changing the "Long" to "Short".
In general, if the input parameter is cast as an INT, the measure is in Ticks. If a DOUBLE, it is usually the price. Also, keep in mind when considering a Short with the description above, flip the CurrentBid/CurrentAsk for the proper reference.
Market Bracket Functions setup and OCO entry for both Long & Short Positions. The current functions setup a StopMarket order at the associated prices. (Todo: Add a GoLimitBracket function to allow for StopLimit feature)
Trend functions setup a StopMarket at the m_RefPrice + number of ticks into the trend.
LOM uses a bit more complex concept for orders than NT. Since LOM allows multiple "BINs" or "Position Numbers" you may want to find the current Market Position of a specific Position (Position 2 Long or Short) or that of all positions (Do you have any LONG or SHORT order open). Either of the following functions can be used to access this position status:
Use the GetMarketPosition() functions like the NT "Position.MarketPosition" built into NT.
LOM uses a bit more complex concept for orders than NT. Since LOM allows multiple "BINs" or "Position Numbers" you may want to find the current Average Fill for a Position. Currently, only the average for each position can be reported. If you have multiple position, you will need to aggregate them manually if you require an overall Fill Average. Either of the following functions can be used to access this position status:
LOM uses a bit more complex concept for orders than NT. Since LOM allows multiple "BINs" or "Position Numbers" you may want to find the current Fill Quantity for a Position. Currently, only the average for each position can be reported. If you have multiple position, you can get the total quantity by leaving out the Position Number. Either of the following functions can be used to access this Fill Quantities:
I have make some headway with the trailing Stop. I have enclosed a sample strategy and some specifics about the following code block:
Here are two different functions shown. SetBreakEven & SetTrailingStop and are used to do just those features. Hopefully this makes the features easier to use. I have enclosed a few DOM shots to show how these features work as it may not be intuitive.
The BreakEven function will bring the StopLoss up relative to the Entry Price. You can see a Short and Long example below with a 3 trigger and a 1 offset. So when the profit (again, NOT LAST) goes to 3, the SL moves to +1. Offset should be able to be set + or - depending upon your need or desire. Also note it is relative to the Entry price. You may opt to only use the TrailingStop feature without a BE.
The TrailingStop feature works very similar. In the DOMs a 4 trigger and 8 trail is selected. The 4 doesn't do much because the BE function will update the position prior to the TrailingStop trigger, experiment by removing the BreakEven function.
These features need to be called for each entry to make sure they are valid and active. Also, the Signal name is simply a unique ID for the feature. So you can create a more complex TrailingStop by assigning "TrailStop1" a 6,8 and "TrailingStop2" as a 20,4 to tighten up after 20 profit ticks much like a complex DOM feature. There should be no actual limit. The system currently only uses 1 tick steps. If there is enough interest I will try to make this configurable.
The trigger levels are the amount of PROFIT in ticks before the action is enabled. This is NOT the amount of Ticks of the Last value and there is a big difference between the two. I have chosen to use Profit and not Last value to help reduce quick Stop Outs.
By using the PROFIT, you avoid a quick stop out because you can see on the DOM where 98.51 is highlighted. If your stop limit is set to 3 in this case and the LAST value was used at 98.51 the next Buyer is waiting at 98.48, 3 ticks lower. If someone buys, you are out. You would think 3 ticks is more than enough buffer but you can see this is not always the case. But if you see how it is implemented, your stop is still deep in the Buy stack 3 ticks so it would take significant movement in that direction to Stop you out. Not as much profit, but you will stay in longer if 98.52 is the next trade after the 98.48, and I will tell you in this case, the market keeps moving up and stopped out at about 20 ticks!
The following is a list of future features to be added to Local order Manager. Please note, no implementation time has been established for these features. Please contribute your time to speed up the process:
Add FillQuantity Functionality
Market if Touched [MIT] orders to simulate NT DOM feature
Simulated Volume Stop - Wait for Bid/Ask volume to drop below level before Fill
Error Checking of LOM market Position vs Broker Market position, should be able to disable this feature
Add Support for back testing with tick based features
Add Email of Screen shot and/or Text when Fill or event occurs
Ability to retrieve any SL & PT set for a position
Rev 2:
Added: public bool GoShortLimit(int m_SharesTraded,double m_Limit,int m_PositionNumber) - To handle true [COLOR=#0066cc]Limit Order, Rather than STOPLIMIT[/COLOR]
Added: public bool GoShortLimit(int m_SharesTraded,int m_LimitTicks,double m_RefPrice,int m_PositionNumber) - To handle true [COLOR=#000080]Limit Order, Rather than STOPLIMIT[/COLOR]
Added: public bool GoLongLimit(int m_SharesTraded,double m_Limit,int m_PositionNumber) - To handle true Limit Order, Rather than STOPLIMIT
Added: public bool GoLongLimit(int m_SharesTraded,int m_LimitTicks,double m_RefPrice,int m_PositionNumber) - To handle true Limit Order, Rather than STOPLIMIT
Rev 3:
Added: public void SetStatsBoxVisable(bool m_Stats)
Added: GoShortStopLimit() Functions, depreciated functions that are misleading
Added: GoLongStopLimit() Functions, depreciated functions that are misleading
Rev 4: 4/1/2012
Added: Various Trailing Stop fixes
Fix: PartialFills improvements
Experimental: Timer functions for future features
Rev 5: 4/15/2012
Fix: Major Stability Improvements, Partial Fills almost flawless
Experimental: Timer functions for future features improved
Rev 6: 7/25/2012 (Beta Release)
Fix: Major Stability Improvements, Partial Fills almost flawless
Fix: Timer functions for Good Until, detects fast replay and autodisables
Added: Good Until by Time & #Bars
Added: Trailing Stop DataSeries Driven
Added: GoLimitBracket
Added: GetFillQuantity
Added: Rejected Order handling (started)
Improved: Entry/exit functions added object to contain rules/handling
Experimental: Timer functions for future features improved
Added: Version ID Current LOM:02b.01b.01a.01.01b.02.01.01a.01.0.0.2
Rev 7: 9/26/2013 (Beta Release)
Update done by contributor, not fully integrated but available. Fix: Fixed a bug in dataseries based SetTrailingStop() in which the the wrong variable is used for calculating the tick offset. Changed: Changed the behavior of the dataseries based SetTrailingStop() such that it will remain triggered after the price has moved beyond the trail trigger ticks and retrace back. The previous implementation is such that the trailing stop will be active only when the price remains beyond the trail trigger ticks. Improved: Commented out the warning logs for non-value dataseries of the indicator based Trailing Stop. It is not necessary for trailing stop indicator to return a value for every bar. For example, a price action swing trailing stop indicator returns an update of a stop loss value after it makes a swing. Furthermore, it is more efficient to update the stop loss value as and when it is required.
Rev 8: 11/24/2014
Update done by contributor, not fully integrated but available. General: Rolled up many improvements into the latest build Added: Added new user contribution "SetStatsBoxVisable(bool m_Stats, string m_DebugString)" to enable and disable Stats box with Debugging String
Added: Version ID Current LOM:02b.01b.01b.01.01b.02a.01.01b.01.0.0.2