📝 概要
今回は、TradingViewのPine Scriptで作成した Turn of the Month (Ultimo) を紹介します。この戦略は、いわゆる Turn of the Month Effect(月末・月初効果) を狙うシンプルなカレンダー戦略です。テクニカル指標は一切使わず、「今日は月末にどれくらい近いか」「翌月の何営業日目か」だけで売買します。
デフォルトでは、月末の6暦日前の日付以降にロングし、翌月の3営業日目に決済します。たとえば31日まである月なら 31 - 6 = 25 なので、25日以降の最初の取引日がエントリー候補です。30日までなら24日以降、2月28日までなら22日以降という具合です。入口は暦日ベースですが、出口は実際のバーを数える営業日ベースになっています。
つまり考え方はかなり単純で、月末が近づいたら買い、翌月序盤まで持つだけ。移動平均線もRSIもMACDも見ません。価格パターンではなく、月末から月初にかけてリターンに偏りがあるのではないか、という季節性そのものを検証するストラテジーです。
今回の修正版では売買ロジックを変えず、その月の最終日とエントリー開始日を毎バー計算するのではなく、月が変わったときだけ計算して保存する形にしています。バックテスト結果を変えずに、無駄な日時計算を少し減らしたバージョンです。
🎯 作成の意図
相場には、曜日、時間帯、月末、月初、祝日前後など、カレンダーに関係するさまざまなアノマリーがあります。Turn of the Monthもそのひとつで、月末から翌月初にかけての一定期間にリターンが偏る可能性を利用します。
この手の戦略の面白いところは、価格を予測するためのテクニカル指標が必要ないことです。「RSIが売られすぎだから反発しそう」「移動平均線を上抜いたから上昇トレンド」といった判断ではなく、月末・月初というタイミングだけにエッジが存在するかをそのまま検証できます。そのため、調整する中心的な要素も「月末の何日前から入るか」「翌月の何営業日目に出るか」という2点だけで、非常にシンプルです。
また、毎月ほぼ同じルールを繰り返すので、株価指数、個別株、FX、Goldなど複数の市場で比較しやすいのもメリットです。もし特定の市場や期間だけで機能するなら、その季節性がどの程度安定しているのかも見えてきます。逆に、少し期間を変えただけで成績が崩れるなら、単なる偶然や過剰最適化の可能性も疑えます。
📘 コード(戦略部分)の解説
この戦略では、その月の最終日から指定した日数を引いて、エントリー開始日を決めています。修正版ではこの値を毎バー計算せず、月が変わったときだけ更新します。
if barstate.isfirst or isNewMonth
int lastDayOfMonth = dayofmonth(timestamp(year, month + 1, 1, 0, 0) - MS_PER_DAY)
entryStartDayOfMonth := lastDayOfMonth - entryLeadCalendarDays
デフォルトの entryLeadCalendarDays は6です。31日まである月なら25日、30日までなら24日がエントリー開始日になります。なお、「最後の6日間」という意味ではなく、月末から6暦日前の日付以降という計算なので、31日の月では25日から31日までが対象になります。
実際のロング条件はこちらです。
enterLong = time >= startDate and time <= endDate and strategy.position_size == 0 and dayofmonth >= entryStartDayOfMonth
if enterLong
strategy.entry("ToM", strategy.long)
つまり、指定期間内でまだポジションを持っておらず、その日の dayofmonth がエントリー開始日以上ならロングします。月末期間中に毎日買い増すわけではなく、strategy.position_size == 0 が入っているため、最初に条件を満たしたところで1回だけエントリーします。
出口では、月が変わった最初のバーを1営業日目としてカウントします。
tradingDayOfMonth := isNewMonth ? 1 : tradingDayOfMonth + 1
そして、現在ロングを保有していて、そのカウントが指定した営業日数に達したら決済します。
exitLong = strategy.position_size > 0 and tradingDayOfMonth == exitTradingDay
if exitLong
strategy.close("ToM", comment="exit_tom")
デフォルトでは exitTradingDay = 3 なので、翌月の3営業日目にクローズします。祝日や土日が入っても、カレンダー上の3日ではなく、実際にバーが存在する3営業日目で決済されます。
したがって、デフォルト設定の戦略ロジックは、「月末の6暦日前の日付以降に1回ロングし、翌月3営業日目に決済する」 というものです。固定pipsの利食いも損切りもなく、価格が上がったか下がったかに関係なく、カレンダーだけで出口まで決まります。
かなりシンプルですが、それがこの戦略の良いところです。余計な条件がないので、バックテストで利益が残るなら「月末から月初」というタイミング自体にどの程度の偏りがあるのかを比較的ストレートに確認できます。
コアメンバー向けソース
こちらからどうぞ。



コメント