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, WLColor.Black, 10); // p.BarsHeld is a constant DrawBarAnnotation(p.BarsHeld.ToString(), idx, false, WLColor.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"), WLColor.Red, 12); DrawHeaderText("Entry Price for the trade was: " + p.EntryPrice.ToString("N2"), WLColor.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. In a Multi-Currency backtest, Commission is given in the base currency. See also: CommissionNonBase
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 total commission (entry plus exit) for the Position. In a Multi-Currency backtest, CommissionNonBase is given in the trade's currency. See also: Commission
Returns the cost basis for the Position in the base currency for a Multi-Currency backtest. This is the Position's EntryPrice multipled by its Quantity and converted to the base currency. In Futures Mode, it is the symbol's Margin multipled by Quantity.
Returns the cost basis for the Position in the trade (non-base) currency. 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
- Returns -1 for Daily and all non-Intraday scales.
- 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. In a Multi-Currency backtest, EntryCommission is given in the base currency. See also: EntryCommissionNonBase
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 entry commission for the Position in the trade's currency for a Multi-Currency backtest. See also: EntryCommission
Returns the DateTime the Position was entered.
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 { Position p = LastPosition; if (bars.Close.CrossesUnder(_ma, idx)) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { //Write a list of Entry and Exit dates to the debug window foreach (Position p in GetPositionsAllSymbols()) { string s = string.Format("{0}\t{1}\t{2:d}\t{3}\t{4:d}", p.Symbol, p.EntryBar, p.EntryDate, p.ExitBar, p.ExitDate); WriteToDebugLog(s); } } } }
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.
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); PlotStopsAndLimits(4); } //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 { Position p = LastPosition; if (idx - p.EntryBar + 1 > 5) PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0, "Time-based"); else { double limit = p.EntryPrice * 1.05; // 5% profit target PlaceTrade(bars, TransactionType.Sell, OrderType.Limit, limit, "5%"); } } } } }
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.MAEPctAsOf(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. In a Multi-Currency backtest, ExitCommission is given in the base currency. See also: ExitCommissionNonBase
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 exit commission for the Position in the trade's currency for a Multi-Currency backtest. See also: ExitCommission
Returns the DateTime the Position was exited. If the Position is still open, returns DateTime.MaxValue.
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 { Position p = LastPosition; if (bars.Close.CrossesUnder(_ma, idx)) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { //Write a list of Entry and Exit dates to the debug window foreach (Position p in GetPositionsAllSymbols()) { string s = string.Format("{0}\t{1}\t{2:d}\t{3}\t{4:d}", p.Symbol, p.EntryBar, p.EntryDate, p.ExitBar, p.ExitDate); WriteToDebugLog(s); } } } }
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.
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 { Position p = LastPosition; if (bars.Close.CrossesUnder(_ma, idx)) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { //Write a list of Entry and Exit dates to the debug window foreach (Position p in GetPositionsAllSymbols()) { string s = string.Format("{0}\t{1:d}\t{2:d}\t{3:N4}", p.Symbol, p.EntryDate, p.ExitDate, p.ExitPrice); WriteToDebugLog(s); } } } }
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.MAEPctAsOf(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 the value of a Position Metric that is either a built-in metric (such as Profit or BarsHeld), or a metric created by calling SetMetric. Typically used within Performance Visualizers such as Position Metrics in the Power Pack Extension. The roster of all available Position Metrics can be obtained via the Backtester.PositionMetricNames property.
Returns the index into the Backtester Positions list that this Position occupies. Used in certain Performance Visualizers, for example Position Metrics (Trade Stability preset) in the Power Pack Extension.
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 is in the base currency for a Multi-Currency backtest and 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
- MAE will be a negative number (or zero).
Returns the Maximum Adverse Excursion (MAE) generated by the Position, as of the specified bar number with commissions applied. MAEAsOf is in the base currency for a Multi-Currency backtest and represents the largest intraday loss that the trade experienced up to and including the specified bar.
Remarks
- MAEAsOf will be a negative number (or zero).
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position with commissions applied. MAENonBase is always in the trade (non-base) currency for a Multi-Currency backtest (see MAE) and 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 MAENonBaseAsOf.
- MAENonBase will be a negative number (or zero).
Returns the Maximum Adverse Excursion (MAE) generated by the Position, with commissions applied, as of the specified bar number. MAENonBaseAsOf represents the largest intraday loss that the trade experienced up to and including the specified bar, always expressed in the trade currency.
Remarks
- MAENonBaseAsOf will be a negative number (or zero).
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position, with commissions applied, as a percentage, as of the specified bar number. MAEPctAsOf represents the largest intraday percentage loss in the base currency for a Multi-Currency backtest that the trade experienced up to and including the specified bar.
Remarks
- MAEPctAsOf will be a negative number (or zero).
- For Futures Mode, MAEPct considers MAE dollar loss and futures margin.
Example (Futures Mode)
2 ES contracts ($50 point value) shorted at 4000.00 advanced to an intraday high of 4050.00, a -1.25% loss "non futures mode". The MAE dollar loss is (2 * $50 * -50) = -$5,000 and for a futures margin of $18,000 per contract, the MAEPct is -5000/36000 * 100 = -13.89%.
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.MAEPctAsOf(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 as of the specified bar number. MAEPctNonBaseAsOf represents the largest intraday percentage loss, always with respect to the trade currency, that the trade experienced up to and including the specified bar.
Remarks
- MAEPctNonBaseAsOf will be a negative number (or zero).
- For Futures Mode, MAEPct considers MAE dollar loss and futures margin.
Returns the Maximum Adverse Excursion (MAE) that was generated by the Position as a percentage. MAEPercent represents the largest intraday percentage loss that the trade experienced during its lifetime. In a Multi-Currency backtest, MAEPercent is with respect to the base currency.
This property is intended for use by Performance Visualizers, and not in Strategies.
Remarks
- Includes commissions.
- During Strategy execution use MAEPctAsOf.
- MAEPercent will be a negative number (or zero).
- For Futures Mode, MAEPercent considers MAE dollar loss and futures margin.
Same as MAEPercent, but always with respect to the trade's currency.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position with commissions applied. MFE is in the base currency for a Multi-Currency backtest and 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 MFEAsOf.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position, with commissions applied, as of the specified bar number. MFEAsOf is in the base currency for a Multi-Currency backtest and 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. MFENonBase is always in the trade (non-base) currency and 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.
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. MFEPctAsOf represents the highest intraday percentage profit with respect to the base currency for a Multi-Currency backtest that the trade experienced up to and including the specified bar.
Remarks
- For Futures Mode, MFEPct considers MFE dollar profit and futures margin.
Example (Futures Mode)
2 long ES contracts ($50 point value) purchased at 4000.00 advanced to an intraday high of 4050.00, a 1.25% rise for "non futures mode". The MFE dollar profit is (2 * $50 * 50) = $5,000 and for a futures margin of $18,000 per contract, the MFEPct is 5000/36000 * 100 = 13.89%.
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.MFEPctAsOf(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 as of the specified bar number. MFEPctNonBaseAsOf represents the largest intraday percentage profit, always with respect to the trade currency, that the trade experienced up to and including the specified bar.
Returns the Maximum Favorable Excursion (MFE) that was generated by the Position 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.
This property is intended for use by Performance Visualizers, and not in Strategies.
Remarks
- In a Multi-Currency backtest, MFEPercent is with respect to the base currency.
- Includes commissions.
- During Strategy execution use MFEPctAsOf.
- MAEPercent will be a negative number (or zero).
- For Futures Mode, MFEPercent considers MFE dollar profit and futures margin.
Same as MFEPercent, but always with respect to the trade's currency.
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. This property is mainly meant for use in Performance Visualizers, not during backtesting. If you need to obtain a Position's profit during a backtest, use ProfitAsOf instead.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class MyStrategy : UserStrategyBase { TimeSeries _sma; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { _sma = SMA.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)) { if (bars.Close.CrossesOver(_sma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { //header string s = String.Format("{0, 12}\t{1}\t{2, 12} vs. {3, 12}{4, 12} vs. {5, 6}", "Symbol", "ExitDate", "WL8 Profit", "My Profit", "WL8 Profit%", "My Profit%"); WriteToDebugLog(s); //let's check Wealth-Lab's Profit calculations! foreach (Position p in GetPositionsAllSymbols()) { int sign = p.PositionType == PositionType.Long ? 1 : -1; double profit = p.Quantity * sign * (p.ExitPrice - p.EntryPrice); double profitPct = 100 * sign * (p.ExitPrice / p.EntryPrice - 1); s = String.Format("{0, 12}\t{1:d}\t{2, 12:C2} vs. {3, 12:C2}{4, 12:N2}% vs. {5, 6:N2}%", p.Symbol, p.ExitDate, p.Profit, profit, p.ProfitPercent, profitPct); WriteToDebugLog(s ); } } } }
Returns the profit of the Position (in the trade currency) as of the specified bar number. Commissions are included in the calculation.
Remarks
- See also MAEAsOf, MFEAsOf
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { _sma = SMA.Series(bars.Close, 20); PlotIndicator(_sma); } //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(_sma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position pos = LastPosition; // exit after 10 bars or a $500 profit if (idx - pos.EntryBar + 1 >= 10) ClosePosition(pos, OrderType.Market, exitSignalName: "Time out"); else if (pos.ProfitAsOf(idx) >= 500) ClosePosition(pos, OrderType.Market, exitSignalName: "$500"); } } //declare private variables below SMA _sma; } }
Returns the percentage profit of the Position as of the specified bar number. Commissions are included in the calculation.
Remarks
- For Futures Mode, ProfitPctAsOf returns the current trade percentage profit with respect to futures margin.
Example (Futures Mode)
2 long ES contracts ($50 point value) purchased at 4000.00 last closed at 4050.00, a 1.25% profit % for "non futures mode". The dollar profit is (2 * $50 * 50) = $5,000, and for a futures margin of $18,000 per contract, the Profit percentage is 5000/36000 * 100 = 13.89%.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { TimeSeries _sma; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { _sma = SMA.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)) { if (bars.Close.CrossesOver(_sma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { //Exit at market (tomorrow) when the closed Position Profit % exceeds 6% or after 20 bars Position p = LastPosition; if (p.ProfitPctAsOf(idx) >= 6) PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0, "Profit %"); else if (idx + 1 - p.EntryBar > 20) PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0, "Time Based"); } } } }
Returns the percentage profit of the Position in the base currency for a Multi-Currency backtest, with commissions deducted.
Remarks
This property is mainly meant for use in Performance Visualizers, not during backtesting. Strategies should use ProfitPctAsOf to obtain a Position's profit % at a specified bar during a backtest.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript2 { public class MyStrategy : UserStrategyBase { TimeSeries _sma; //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { _sma = SMA.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)) { if (bars.Close.CrossesOver(_sma, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } public override void BacktestComplete() { //header string s = String.Format("{0, 12}\t{1}\t{2, 12} vs. {3, 12}{4, 12} vs. {5, 6}", "Symbol", "ExitDate", "WL8 Profit", "My Profit", "WL8 Profit%", "My Profit%"); WriteToDebugLog(s); //let's check Wealth-Lab's Profit calculations! foreach (Position p in GetPositionsAllSymbols()) { int sign = p.PositionType == PositionType.Long ? 1 : -1; double profit = p.Quantity * sign * (p.ExitPrice - p.EntryPrice); double profitPct = 100 * sign * (p.ExitPrice / p.EntryPrice - 1); s = String.Format("{0, 12}\t{1:d}\t{2, 12:C2} vs. {3, 12:C2}{4, 12:N2}% vs. {5, 6:N2}%", p.Symbol, p.ExitDate, p.Profit, profit, p.ProfitPercent, profitPct); WriteToDebugLog(s ); } } } }
Returns the number of shares or contracts that comprise the Position.
Contains the established stop loss level of the trade that was used for Max Risk Percent position sizing. You can use this value to issue stop loss orders for open positions so the maximum loss of the trade does not exceed the desired maximum risk.
Adds a Position Metric with the specified metricName and value. Position Metrics are typically added at the Transaction level, using the Transaction SetPositionMetric method, but they can also be assigned directly to Positions. For example, during the BacktestComplete method. Certain Performance Visualizers, for example the Position Metrics in the Power Pack Extension, access Position Metrics.
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.
Returns the dollar size of the Position as of the specified bar index. In a Multi-Currency Backtest, this value is in the base currency. For equities and mutual funds this is the shares multiplied by the entry price (CostBasis property). For futures, this is the contracts multiplied by the margin of the contract.