Parent:
Covers a list of DateTime extension methods that assist with typical trading functions related to date and time. Call these methods like any other DateTime method using the method syntax. The first parameter, always this DateTime, specifies the type that the method operates on. See the examples for usage details.
Returns the number of calendar days between fromDate and toDate. The result is positive if toDate is in the future, otherwise zero (same Date) or negative.
Remarks
- If the string date overload is used, the date string must use the "yyyyMMdd" format, e.g. "20210416"
- If the int date overload is used, the date int must use the yyyyMMdd format, e.g, 20210416
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) { DateTime exp = bars.DateTimes[idx].NextOptionExpiryDate(bars); int calendarDaysToExpiry = bars.DateTimes[idx].CalendarDaysBetweenDates(exp); //annotate the bars with number of calendar days to Expiry DrawBarAnnotation(calendarDaysToExpiry.ToString(), idx, true, WLColor.Black, 9, true); } } }
Returns the DateTime the next trading day after dt for the bars or mkt. If the date passed to the method contains a time, it is preserved in the result. This method is useful to determine if the next day is the end of the week/month for signaling.
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) { } //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 the next day is the end of the month, buy on the close if (bars.DateTimes[idx].GetNextTradingDate(bars).IsLastTradingDayOfMonth(bars)) PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose, 0, "End of Month"); } else { //exit the Position at the Close on the last day of the first week if (bars.DateTimes[idx].GetNextTradingDate(bars).IsLastTradingDayOfWeek(bars)) PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose, 0, "End of Week"); } } } }
Returns the 24-hour 'HHmm' integer of the time part of dt. Seconds are ignored. This method is useful to create time-of-day trading filters without resorting to the use of TimeSpan.
Examples
- 9:35 am => 935
- 12:00 pm => 1200
- 3:50 pm => 1550
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)) { // don't enter before 10:15 am if (bars.DateTimes[idx].GetTime() < 1015) return; // after 10:15, buy if the close is above the moving avg if (bars.Close[idx] > _sma[idx]) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { // sell on 2 consecutive closes below the moving avg if (bars.Close[idx] < _sma[idx] && bars.Close[idx - 1] < _sma[idx - 1]) ClosePosition(LastPosition, OrderType.Market); } } SMA _sma; } }
Returns true if the DateTime dt is a holiday for the specifed BarHistory bars, otherwise false.
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 _dayBeforeHoliday; public override void Initialize(BarHistory bars) { //create a series that marks the day before a holiday with a 1 _dayBeforeHoliday = new TimeSeries(bars.DateTimes, 0); DateTime nextDate; for (int bar = 0; bar < bars.Count; bar++) { //check if the next non-weekend day (in the future) is a holiday nextDate = bars.DateTimes[bar].Date; do { nextDate = nextDate.AddDays(1); int day = (int)nextDate.DayOfWeek; if (day == 0 || day == 6) //skip Sunday or Saturday continue; if (nextDate.IsHoliday(bars)) _dayBeforeHoliday[bar] = 1; break; } while (true); if (_dayBeforeHoliday[bar] == 1) SetBackgroundColorAllPanes(bars, bar, WLColor.FromArgb(40, WLColor.Green)); } } public override void Execute(BarHistory bars, int idx) { } } }
Returns true if the Date is the last trading day of a calendar month for the specifed BarHistory, otherwise false.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; 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) { } //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.DateTimes[idx].IsLastTradingDayOfMonth(bars)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { Position p = LastPosition; //sell after 5 bars if (idx + 1 - p.EntryBar >= 5) ClosePosition(p, OrderType.Market, 0, "Time-based"); } } //declare private variables below } }
Returns true if the Date is the last trading day of a calendar week for the specifed BarHistory, otherwise false.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; 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) { PlotStopsAndLimits(3); _ib = Highest.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)) { PlaceTrade(bars, TransactionType.Buy, OrderType.Stop, _ib[idx]); } else { Position p = LastPosition; //exit the Position at the Close on the last day of the week if (bars.DateTimes[idx].GetNextTradingDate(bars).IsLastTradingDayOfWeek(bars)) PlaceTrade(bars, TransactionType.Sell, OrderType.MarketClose, 0, "End of Week"); } } //declare private variables below IndicatorBase _ib; } }
The first version without the BarHistory parameter returns true if the date corresponds to the third Friday of a month, which is generally the monthly option expiration day. Otherwise the function returns false. The BarHistory overload allows the function to detect if the third Friday is a market holiday in which case the function will return true on the Thursday before the Friday holiday. Example: The U.S. Market celebrated Good Friday on 4/14/2022, consequently monthly options expired on 4/13/2022.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) { //make the background light blue on option expiry day if (bars.DateTimes[idx].IsOptionExpiry()) SetBackgroundColorAllPanes(bars, idx, WLColor.FromArgb(40, WLColor.Blue)); } } }
Returns true if the market trades on the day represented by DateTime dt. Time is ignored.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; 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) { //will the market trade on Dec 25, 2045? DateTime dte = new DateTime(2022, 12, 25); WriteToDebugLog("The market will trade on Dec 25, 2045: " + dte.IsTradingDay(bars)); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { } } }
Returns true if the DateTime dt falls on a Saturday or Sunday. This is a helper function that's used when calculating the next trading day, for example, but adding days to a date and checking if the result falls on a weekend or a holiday.
Returns DateTime of the next closest monthly options expiration date as of the specified date. Options expiration dates typically fall on the third Friday of every month.
Remarks
- Returns the current date if it is an expiry date
- If expiry Friday is a holiday, returns Thursday's date prior to the holday.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) { //make the background light blue on option expiry day if (bars.DateTimes[idx].IsOptionExpiry()) SetBackgroundColor(bars, idx, WLColor.FromArgb(40, WLColor.Blue)); if (!HasOpenPosition(bars, PositionType.Long)) { //buy 4 trading day before the next option expiry //using BarHistory method int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], bars.NextOptionExpiryDate(idx)); //since we buy on next bar, test for 5 days if (daysToExpiry == 5) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); } else { //get the expiry after the position entry bar DateTime expiryAfterEntry = bars.NextOptionExpiryDate(LastPosition.EntryBar); //now get the following expiry date using the DateTime extension method DateTime nextExpiry = expiryAfterEntry.AddDays(1).NextOptionExpiryDate(bars); int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], nextExpiry); //sell 11 trading days before the next expiry if (daysToExpiry == 12) PlaceTrade(bars, TransactionType.Sell, OrderType.Market); } } } }
Returns the DateTime of the trading day prior to the DateTime dt for the MarketDetails md. If dt has a time component, this is retained in the returned result.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { //find the previous trading date 1 year from the last bar DateTime dt = bars.DateTimes[bars.Count - 1].AddYears(1); DateTime prevTradingDay = dt.PreviousTradingDay(bars.Market); WriteToDebugLog("The current date is " + dt.ToString("yyyy-MM-dd HH:mm")); WriteToDebugLog("The trading day prior date 1 year from now is " + prevTradingDay.ToString("yyyy-MM-dd HH:mm")); } public override void Execute(BarHistory bars, int idx) { } } }
Returns a number for the week of the year, 1 to 52 or 53.
Remarks
- Week #1 is the first full week in January, days from Sunday to Saturday.
- Unless Jan 1st is on Sunday, the first days in Jan will often be the last days in the last week of the previous year.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; namespace WealthScript123 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { StartIndex = 1; } public override void Execute(BarHistory bars, int idx) { //identify the first day of the week by its WeekOfYear number int woy = bars.DateTimes[idx].WeekOfYear(); if (woy != bars.DateTimes[idx - 1].WeekOfYear()) DrawBarAnnotation(woy.ToString(), idx, true, WLColor.NeonGreen, 14); } } }