Parent: Object
The Position class represents a long (result of a buy order) or short (result of a sell short order) position that was generated by the backtester.
Returns the BarHistory instance that this Position was based on. Certain Strategies (such as pairs trading or symbol rotation) can trade on multiple symbols. The Bars property allows you to determine which symbol a particular Position was established on, for example.
Remarks
- See the BarHistory class reference for more information about its properties and events.
Returns the number of bars that the position was held. If the Position is still active, BarsHeld returns the total number of bars held as of the last bar of the chart.
Remarks
- The BarsHeld property is primarily intended for use by Performance Visualizers, not Strategies.
- See example to get the current number of bars held for an active position.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class BarsHeldExample : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = bars.Count - 20; } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position p = LastPosition; int currentBarsHeld = idx - p.EntryBar + 1; DrawBarAnnotation(currentBarsHeld.ToString(), idx, true, Color.Black, 10); // p.BarsHeld is a constant DrawBarAnnotation(p.BarsHeld.ToString(), idx, false, Color.Red, 10); } } } }
A Position's "basis price" is the price that was used to establish how many shares the Position should be sized to. For OrderType Market and MarketClose, the basis price is typically the closing price of the previous bar, but this may be changed in the Strategy Settings to be the opening price of the trade bar. For limit/stop orders, the basis price is always the limit/stop price specified.
The actual entry price can of course differ because the market may open above or below the previous close or limit/stop price specified. In certain situations this difference can cause a trade to not be filled by the backtester due to Not Sufficient Funds, and are marked as NSF positions. For more information see Help > Strategy > Strategy Settings > Basis Price.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class BasisPriceExample : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = bars.Count - 20; } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position p = LastPosition; if (idx == bars.Count - 1) { DrawHeaderText("Basis Price for the trade was: " + p.BasisPrice.ToString("N2"), Color.Red, 12); DrawHeaderText("Entry Price for the trade was: " + p.EntryPrice.ToString("N2"), Color.Red, 12); } } } } }
Allows Broker Adapters to store broker-specific information along with a Position, for the purposes of mapping the Position back to a broker-specific identifier.
Returns the total commission (entry plus exit) for the Position.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class CommissionExample : UserStrategyBase { IndicatorBase _ma; public override void Initialize(BarHistory bars) { StartIndex = 20; _ma = SMA.Series(bars.Close, 20); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (bars.Close.CrossesOver(_ma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { if (idx - LastPosition.EntryBar + 1 > 5) // wait at least 5 bars if (bars.Close[idx] < _ma[idx]) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { base.BacktestComplete(); foreach (Position p in GetPositions()) { WriteToDebugLog("Position Entry Date: " + p.EntryDate.ToShortDateString()); WriteToDebugLog("Commission (total): $" + p.Commission.ToString("N2")); WriteToDebugLog("EntryCommission: $" + p.EntryCommission.ToString("N2")); if (p.ExitDate != DateTime.MaxValue) { WriteToDebugLog("Position Exit Date: " + p.ExitDate.ToShortDateString()); WriteToDebugLog("ExitCommission: $" + p.ExitCommission.ToString("N2")); } else WriteToDebugLog("Position Exit Date: Active"); WriteToDebugLog(""); } } } }
Returns the cost basis for the Position. This is the Position's EntryPrice multipled by its Quantity. In Futures Mode, it is the symbol's Margin multipled by Quantity.
Returns how many trading days have passed since establishing a Position when using intraday data.
Remarks
- Pass false to countByLastBarOfDay for DaysInPosition to return 1 on the trading day after which the position was entered.
- Pass true to countByLastBarOfDay for DaysInPosition to return 1 on the last bar of the trading day on which the position was entered - even if the Position is entered on the last bar of the day.
using WealthLab.Backtest; using System; using WealthLab.Core; using System.Drawing; using System.Collections.Generic; namespace WealthScript3 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) { if (bars.IsIntraday) { if (!HasOpenPosition(bars, PositionType.Long)) { //enter on the 4th bar of the day if (bars.IntradayBarNumber(idx) == 3) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { if (LastPosition.DaysInPosition(idx, false) > 3) ClosePosition(LastPosition, OrderType.Market, 0, "Exited after 3 days"); } } } } }
Returns the bar number into the source BarHistory (Bars property) where the Position entry occurred.
Remarks In development of Position Sizers and Performance Visualizers, checking for EntryBar or ExitBar may produce unexpected results because the historical DataSets aren't synchronized when backtesting.
Solution: check for the date with EntryDate/ExitDate rather than the bar number.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class EntryBarExample : UserStrategyBase { IndicatorBase _ma; public override void Initialize(BarHistory bars) { StartIndex = 20; _ma = SMA.Series(bars.Close, 20); PlotIndicatorLine(_ma); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (bars.Close.CrossesOver(_ma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { if (idx - LastPosition.EntryBar + 1 > 5) // wait at least 5 bars if (bars.Close[idx] < _ma[idx]) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } } }
Returns the entry commission for the Position.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class CommissionExample : UserStrategyBase { IndicatorBase _ma; public override void Initialize(BarHistory bars) { StartIndex = 20; _ma = SMA.Series(bars.Close, 20); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (bars.Close.CrossesOver(_ma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { if (idx - LastPosition.EntryBar + 1 > 5) // wait at least 5 bars if (bars.Close[idx] < _ma[idx]) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { base.BacktestComplete(); foreach (Position p in GetPositions()) { WriteToDebugLog("Position Entry Date: " + p.EntryDate.ToShortDateString()); WriteToDebugLog("Commission (total): $" + p.Commission.ToString("N2")); WriteToDebugLog("EntryCommission: $" + p.EntryCommission.ToString("N2")); if (p.ExitDate != DateTime.MaxValue) { WriteToDebugLog("Position Exit Date: " + p.ExitDate.ToShortDateString()); WriteToDebugLog("ExitCommission: $" + p.ExitCommission.ToString("N2")); } else WriteToDebugLog("Position Exit Date: Active"); WriteToDebugLog(""); } } } }
Returns the DateTime the Position was entered.
Returns the type of order that was used to establish the Position. Possible values are:
- OrderType.Market
- OrderType.Limit
- OrderType.Stop
- OrderType.MarketClose
- OrderType.LimitMove
- OrderType.FixedPrice
Returns the price at which the Position was entered.
Contains the SignalName string that was used by the Transaction object that opened this position .The value that you specify is visible in the Positions list and is also accessible via this EntrySignalName property.
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class EntryExitSignalsExample : UserStrategyBase { IndicatorBase _sma; IndicatorBase _smaSlow; IndicatorBase _rsi; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = 100; PlotStopsAndLimits(4); _sma = SMA.Series(bars.Close, 50); _smaSlow = SMA.Series(bars.Close, 100); _rsi = RSI.Series(bars.Close, 10); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { //buy the crossover if (_sma.CrossesOver(_smaSlow, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, "SMA Xing"); //buy a selloff if (_rsi.CrossesUnder(30, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, "RSI<30"); } else { Position p = LastPosition; double tgt = p.EntryPrice * 1.20; //20% gain double stop = p.EntryPrice * 0.75; //-25% stop string exitSignal = "Stop"; // change target to break even if the MAEPercent reaches -10% if (p.MAEAsOfBarPercent(idx) < -10) { tgt = p.EntryPrice; exitSignal = "break even"; } PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, stop, "stop loss"); PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, tgt, exitSignal); } } } }
Returns the bar number into the source BarHistory (Bars property) where the Position exit occurred. If the Position is still open, returns -1.
Remarks In development of Position Sizers and Performance Visualizers, checking for EntryBar or ExitBar may produce unexpected results because the historical DataSets aren't synchronized when backtesting.
Solution: check for the date with EntryDate/ExitDate rather than the bar number.
Returns the exit commission for the Position.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class CommissionExample : UserStrategyBase { IndicatorBase _ma; public override void Initialize(BarHistory bars) { StartIndex = 20; _ma = SMA.Series(bars.Close, 20); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (bars.Close.CrossesOver(_ma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { if (idx - LastPosition.EntryBar + 1 > 5) // wait at least 5 bars if (bars.Close[idx] < _ma[idx]) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { base.BacktestComplete(); foreach (Position p in GetPositions()) { WriteToDebugLog("Position Entry Date: " + p.EntryDate.ToShortDateString()); WriteToDebugLog("Commission (total): $" + p.Commission.ToString("N2")); WriteToDebugLog("EntryCommission: $" + p.EntryCommission.ToString("N2")); if (p.ExitDate != DateTime.MaxValue) { WriteToDebugLog("Position Exit Date: " + p.ExitDate.ToShortDateString()); WriteToDebugLog("ExitCommission: $" + p.ExitCommission.ToString("N2")); } else WriteToDebugLog("Position Exit Date: Active"); WriteToDebugLog(""); } } } }
Returns the DateTime that the Position was exited (closed) on. If the Position is still active, ExitDate returns DateTime.MinValue.
Returns the DateTime the Position was exited. If the Position is still open, returns DateTime.MaxValue.
Returns the type of order that was used to close the Position. Possible values are:
- OrderType.Market
- OrderType.Limit
- OrderType.Stop
- OrderType.MarketClose
- OrderType.FixedPrice
Returns the price at which the Position was exited. If the Position is still open, returns zero.
Contains the SignalName string that was used by the Transaction object that closed this position. The value that you specify is visible in the Positions list for Exit Signal and is also accessible via this ExitSignalName property. If the Position is still active, ExitSignalName returns a blank string.
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class EntryExitSignalsExample : UserStrategyBase { IndicatorBase _sma; IndicatorBase _smaSlow; IndicatorBase _rsi; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = 100; PlotStopsAndLimits(4); _sma = SMA.Series(bars.Close, 50); _smaSlow = SMA.Series(bars.Close, 100); _rsi = RSI.Series(bars.Close, 10); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { //buy the crossover if (_sma.CrossesOver(_smaSlow, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, "SMA Xing"); //buy a selloff if (_rsi.CrossesUnder(30, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, "RSI<30"); } else { Position p = LastPosition; double tgt = p.EntryPrice * 1.20; //20% gain double stop = p.EntryPrice * 0.75; //-25% stop string exitSignal = "Stop"; // change target to break even if the MAEPercent reaches -10% if (p.MAEAsOfBarPercent(idx) < -10) { tgt = p.EntryPrice; exitSignal = "break even"; } PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, stop, "stop loss"); PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, tgt, exitSignal); } } } }
Returns true if the Position was operating under Futures Mode. This will be true if Futures Mode was turned on in Backtest Settings, and the Position's symbol (Bars.Symbol) has a Point Value and Margin defined.
Returns true if the Position is currently open (not yet exited).
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position with commissions applied. MAE represents the largest intraday loss that the trade experienced during its lifetime. This property is intended for use by Performance Visualizers and not in Strategies.
- Remarks * During Strategy execution use MAEAsOfBar.
Returns the Maximum Adverse Excursion (MAE) generated by the Position, with commissions applied, as of the specified bar number. MAEAsOfBar represents the largest intraday loss that the trade experienced up to and including the specified bar.
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position, with commissions applied, as a percentage, as of the specified bar number. MAEAsOfBarPercent represents the largest intraday percentage loss that the trade experienced up to and including the specified bar.
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class MAEExample : UserStrategyBase { IndicatorBase _sma; IndicatorBase _smaSlow; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = 100; PlotStopsAndLimits(4); _sma = SMA.Series(bars.Close, 50); _smaSlow = SMA.Series(bars.Close, 100); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (_sma.CrossesOver(_smaSlow, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position p = LastPosition; double tgt = p.EntryPrice * 1.20; //20% gain double stop = p.EntryPrice * 0.75; //-25% stop string exitSignal = "Stop"; // change target to break even if the MAEPercent reaches -10% if (p.MAEAsOfBarPercent(idx) < -10) { tgt = p.EntryPrice; exitSignal = "break even"; } PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, stop); PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, tgt, exitSignal); } } } }
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position, with commissions applied, as a percentage. MAEPercent represents the largest intraday percentage loss that the trade experienced during its lifetime. This property is intended for use by Performance Visualizers, and not in Strategies.
Remarks During Strategy execution use MAEAsOfBarPercent.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position with commissions applied. MFE represents the highest intraday profit that the trade experienced during its lifetime. This property is intended for use by Performance Visualizers and not in Strategies.
Remarks During Strategy execution use MFEAsOfBar.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position, with commissions applied, as of the specified bar number. MFEAsOfBar represents the highest intraday profit that the trade experienced up to and including the specified bar.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position, with commissions applied, as a percentage and as of the specified bar number. MFEAsOfBarPercent represents the highest intraday percentage profit that the trade experienced up to and including the specified bar.
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript1 { public class MFEExample : UserStrategyBase { IndicatorBase _sma; IndicatorBase _smaSlow; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { StartIndex = 100; PlotStopsAndLimits(4); _sma = SMA.Series(bars.Close, 50); _smaSlow = SMA.Series(bars.Close, 100); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { if (_sma.CrossesOver(_smaSlow, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position p = LastPosition; // change to a trailing stop when MFE Percent reaches 15% if (p.MFEAsOfBarPercent(idx) > 15) { PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, _sma.GetHighest(idx, idx - p.EntryBar)); } else { double tgt = p.EntryPrice * 1.20; //20% gain double stop = p.EntryPrice * 0.85; //-15% stop PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, stop); PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, tgt); } } } } }
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position, with commissions applied, as a percentage. MFEPercent represents the highest intraday percentage profit that the trade experienced during its lifetime. This property is intended for use by Performance Visualizers, and not in Strategies.
Remarks During Strategy execution use MFEAsOfBarPercent.
Contains an int tag value that you can establish at the time the Position is entered. The PlaceTrade method has a positionTag parameter where you can tag Positions for identification. These Positions can be located at a later point by calling FindPosition.
Returns the position type, possible values are PositionType.Long and PositionType.Short.
Returns the profit of the Position, with commissions deducted.
Returns the profit that was generated by the Position, including commissions, as of the specified bar number.
Returns the percentage profit of the Position, with commissions deducted.
Returns the percentage profit that was generated by the Position, including commissions, as of the specified bar number.
Returns the number of shares or contracts that comprise the Position.
Lets you store Strategy-specific information with a Position. If you assigned a value to the Tag property of the Transaction instance that opened this Position, that Tag value will be passed along to the Position.
Provides access to the most recent trailing stop value for the Position. Trailing stop levels come from calling the CloseAtTrailingStop WealthScript method. The trailing stop is adjusted upward if the most recently passed value is higher than the current stop level.