Some input on using dates would be appreciated. I'm working on a rotational strategy (I've used both the AmiBroker rotation method and just general method of strategy creation). Question I have is around dates executing properly.
I essentially would like to stay in positions for at least X number of days but have it exit as close as possible to a certain day of the month (BuyDayofMonth). Any suggestions for code improvements would be much appreciated. If I'm using 28 as the BuyDayofMonth, I'd like to get out the next month as close to the 28th as possible.
I'm currently using the following... I'm getting average exit days in the range I want but several get out 3 or so days earlier than I'd like. Thank you.
You seem to use "days" and "bars" interchangeably. Please keep in mind that "bars" are not "days". "bars" are trading days, excluding Sundays and Saturdays. BarsSince gives you bars, while Day() gives you calendar days.
Here is some code I've used in the past to identify the first day on or after the target day of the month. You could modify this logic a bit to get the first day or or before the target day. To @Tomasz' point, this code assumes you are operating on daily bars.
rotationDay = 15; // Day of the month, 1-28
mth = Month();
dayOfMonth = Day();
// Today is a rotation day if it's the first day on or after the rotation day of month, and the
// previous day was either an earlier day of the month or the end of the previous month
isRotDay = dayOfMonth >= rotationDay AND
(mth != Ref(mth,-1) OR Ref(dayOfMonth,-1) < rotationDay1);
I modified the code a little as my strategy was skipping over Feb trades each year and giving me 11 rotations per year instead of 12. I limited the total number of trading days per month to 22 also because of data and date issues with some of the exits, it would sometimes not get out of a trade and therefore stay in a few "anomalous" trades for over 40 days (2 months or so) when it would miss the exit day. Here's my modified code... thanks again!
rotationDay = param("Rotation Day of Month", 28, 1, 31, 1);
rotationDayFeb = Param("Rotation Day for Feb", 26, 1, 31, 1);
mth = Month();
dayOfMonth = Day();
isRotDay = dayOfMonth >= rotationDay AND (mth != Ref(mth,-1) OR Ref(dayOfMonth,-1) < rotationDay);
isRotDayFeb = dayOfMonth >= rotationDayFeb AND (mth != Ref(mth,-1) OR Ref(dayOfMonth,-1) < rotationDayFeb);
Buy = IIf(mth == 2, dayOfMonth >= rotationDayFeb AND Ref(dayOfMonth,-1) < rotationDayFeb, dayOfMonth >= rotationDay AND Ref(dayOfMonth,-1) < rotationDay);
Sell = IIf(mth == 2, isRotDayFeb OR BarsSince(Buy) >= 22, isRotDay OR BarsSince(buy) >= 22);
@DaveDM instead of "calendar dates" have you considered using trading day of the month (which if using Daily bars is Trading Bar of the month)? Like calendar dates it will vary from month to month (past few years 19-23 trading days per month in North American markets).
Many ways to code a count of days or a specific day, here are some examples.
// Counting the actual Trading Days each month
// And just for an example exploring for the 1st trading day
// in any given month
TradingDayThisMonth = BarsSince( Day() < Ref(Day(),-1) ) + 1;
FirstDay = TradingDayThisMonth==1;
// in AmiBroker there are many ways to arrive at the same endpoint
// the following code arrives at the same result as the above code
alternateCode = BarsSince(Month() != Ref( Month(), -1) )+1;
// another interesting day is often the first trading day of the month
isFirstOfMonth = Month() != Ref(Month(),-1);
// another method looking at Last trading day of month
LastDayOfMonth = TimeframeExpand(1, inMonthly, expandPoint);
Filter=1;
AddColumn(TradingDayThisMonth, "TradingDayThisMonth", 1.0);
AddColumn(alternateCode, "alternateCode", 1.0);
AddColumn( FirstDay,"First Day",1,colorBlue, IIf(FirstDay, colorYellow,colorDefault));
AddColumn( isFirstOfMonth,"another First Day", 1,colorWhite, IIf(isFirstOfMonth, colorBlue,colorDefault));
AddColumn(LastDayOfMonth, "Last Day", 1.0, colorWhite, IIf(LastDayOfMonth, colorRed, colorDefault));
A debugging Explore produces these types of result,
@DaveDM: You're correct that this logic did not work consistently when defining a rotation day very close to the end of the month. I originally wrote it for use near the beginning or middle of each month. EOM logic would work better if we chose a day less than or equal to the rotation day rather than greater than or equal to the rotation day.
Glad that you got your solution working. You could probably use isRotDay and isRotDayFeb inside your Buy= assignment rather than repeating all that logic.
@portfoliobuilder: Good idea regarding using the trading day of the month rather than the calendar day.
Does anyone have a concise function for BarsTillEndOfTheMonth?
Utilizing historical EOD database would be the easiest, I just can't think of doing it right now without finding end of the month as above isEndOfMonth = TimeFrameExpand(1,inMonthly,expandPoint);
and then checking 23 times (there are up to 23 bars or trading days in a month) which day it is until then. I'd like for it to return an integer, positive or negative, with how many bars from current date until end of the month.