ページカレンダーデータ · 13 / 29
カレンダーモジュール
カレンダーモジュールは、戦略に企業の配当履歴、株式分割履歴、決算日、IPO 日、直近の SEC 提出書類を提供し、バックテストが分割と配当をポジションに自動で適用できるようにします。
Run backtest モーダルの Symbol & data タブで Include calendar data を有効にします。既定でオンで、選択内容(および 2 つのサブオプション)は次回の実行用に記憶されます。カレンダーは、スクリーナーで解決されたユニバースを含め、実行が取引するすべての銘柄について自動で読み込まれます — 銘柄ごとのピッカーはありません。エージェントの Test モーダルにも同じオプション Include calendar data (dividends, splits) があります(エージェント を参照)。
バックテストのみ。 カレンダーデータは、バックテスト、Debug Test、エージェントのテストで読み込まれます。フォワード実行(chart forward テスト、AutoTrading の bulk 実行、QuantCloud)ではカレンダーが提供されることはなく、そこでは calendar は常に None です。
なぜ重要か: 価格バーは生のまま
バックテストのローソク足は未調整です。カレンダーデータがないと:
- 4 対 1 の株式分割が一夜にして 75% の価格暴落に見え、シミュレートされたポジションも一緒に暴落します。
- 配当が一切入ってこないため、長期保有ポジションの総リターンが静かに過小評価されます — 一般的な配当銘柄で年約 2% です。
2 つのサブオプションは、コードの変更なしにどちらも解消します。
calendar コールバックパラメータ
任意のコールバックに calendar パラメータを追加すると、ハンドルが渡されます。
def on_bar(bar_index, bar, calendar=None, symbol=None):
if calendar is None: # always guard — not every run enables calendar data
return
days = calendar.days_to_earnings(bar["t"], symbol)
if days is not None and days <= 2:
return # sit out the earnings print
divs = calendar.dividends(bar["t"], symbol)
if divs and (divs[-1].amount or 0) > 0.5: # amount can be None
...on_bar、on_tick、on_timer で動作します。calendar 引数は名前でマッチされるため、calendar パラメータのないスクリプトは以前とまったく同じに動作し、宣言された calendar にはハンドルか None のどちらかが渡されます — シグネチャが他に何を受け取っていても、別のオブジェクトが渡されることはありません。ファンダメンタルズも読む場合の推奨シグネチャは def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None) です。
パラメータなしでも同じハンドルにアクセスできます: スクリプトのグローバル qc_calendar、または quantcraft.process.runtime.qc_calendar。
メソッド
| メソッド | 戻り値 |
|---|---|
dividends(bar_time, symbol=None) | そのバー時点で公開されている配当 |
splits(bar_time, symbol=None) | そのバーまでに発表された分割 |
filings(bar_time, symbol=None) | そのバー時点で公開されている SEC 提出書類 |
next_earnings(bar_time, symbol=None) | {date, basis, estimated, …} または None |
days_to_earnings(bar_time, symbol=None) | int または None |
ipo_date(symbol=None) | date または None |
current(bar_time, symbol=None) | そのバー時点の上記すべてのスナップショット辞書、または None |
dividends_between(start, end, symbol=None) | 権利落ち日が (start, end] に入る配当 |
splits_between(start, end, symbol=None) | 効力発生日が (start, end] に入る分割 |
has(symbol=None) | この銘柄にカレンダーデータがあるかどうか |
symbols / primary_symbol() / get(symbol=None) | 読み込まれた銘柄、既定の銘柄、銘柄ごとの生のカレンダー(または None) |
_between メソッドは影響が及ぶ日付(「いつポジションに影響するか?」)を使います。上のバー時刻のメソッドが「知り得たか?」の日付を使うのとは異なります — 次のセクションを参照してください。
bar_time には、bar["t"]、bar.t[0]、datetime、date、エポック秒を指定できます。
リストは古い順です — dividends(...)[-1] が最新です。これは、インデックス 0 が最新期間であるファンダメンタルズとは逆です。
カレンダーデータのない銘柄は [] または None を返し、エラーにはなりません。 大型株以外のほとんどのティッカーはサーバーにカレンダーがないため、例外ではなく空であるかどうかで判定してください。
イベントごとの 2 つの日付 — 正しいほうを使う
すべての配当と分割には2 つの日付があり、間違ったほうを選ぶと先読みバイアスが入ります。
| 「知り得たか?」 | 「いつポジションに影響するか?」 | |
|---|---|---|
| 配当 | declaration_date | ex_date |
| 分割 | filing_date | effective_date |
dividends() / splits() / filings() は最初の列で絞り込みます。つまり、そのバー時点で公開されていたものだけを返します。8-K は事前に提出されるため、分割は効力発生の数週間前から見えることがよくあります。
from datetime import date
bar_date = date.fromisoformat(str(bar["t"])[:10])
splits = calendar.splits(bar["t"], symbol)
upcoming = [s for s in splits
if s.effective_date and s.effective_date > bar_date] # announced, not yet effectiveイベントのフィールド
DividendEvent: ex_date, amount, estimated, type, declaration_date,
record_date, payment_date, period_end
SplitEvent: effective_date, ratio, type ("forward" | "reverse"), filing_date, form
FilingEvent: form, filing_date, report_date, items, category,
accession_number, primary_document, primary_document_description
IpoInfo: date, first_trade_date, sourceamount(配当)と effective_date(分割)は None の場合があります — 比較する前に確認してください。
提出書類の category は、earnings、acquisition、officer-director、charter-amendment、agreement、regulation-fd、auditor-change、shareholder-vote、cybersecurity、other のいずれかです。
estimated フラグ
EDGAR は配当権利落ち日を公表していません。取引所のデータが利用できない場合、権利落ち日は宣言日 + 10 日として推定され、精度はおよそ ±7 日で、estimated is True となります。既定では、シミュレーションは推定された配当も引き続き入金します(ポリシー best_available)。実行プリセット (.qcs) で dividendDatePolicy を exact_only(推定のものをスキップ)または off に設定できます — モーダルにはこのためのコントロールはありません。戦略が権利落ち日に敏感な場合は、自前のロジックでこれを使って絞り込んでください。
exact = [d for d in calendar.dividends(bar["t"], symbol) if not d.estimated]シミュレーションでのコーポレートアクション
カレンダーデータが有効なとき、2 つのサブオプションはどちらも既定でオンで、どちらもバーごとに、コールバックの前に実行されます。そのため on_bar は常に調整済みのポジションを見ます。
株式分割に合わせてポジションを調整 — 効力発生日に、株数に比率が掛けられ、取得原価はそれで割られます。ストップとターゲットの価格も再スケールされます。qty × entry_price は変わらないため、資産曲線は分割をまたいでも連続したままです。
価格バーは意図的に未調整のままで、bar["close"] は実際の過去の価格です。生の終値系列に対して計算したインジケーターには、分割によるギャップがそのまま見えます。それが問題になる場合は、calendar.splits(...) を使って自前の系列を調整してください。
配当を現金に入金 — 権利落ち日に、qty × amount がロングでは現金に加算され、ショートでは減算されます(空売りした側は貸し手に配当を支払う義務があります)。これは資産とすべてのリターン指標に反映されますが、取引のみを対象とする realized_pnl には反映されません。合計はアカウント指標から読み取ります。
def on_finish(bars, symbol=None, bars_by_symbol=None):
from quantcraft.process.runtime import account
m = account.refresh_metrics({})
print(m["total_dividend_income"], m["total_splits_applied"])コーポレートアクションの確認場所
ポジションや現金が黙って変更されることはありません。
- 出力パネル — 適用されたコーポレートアクションごとに 1 行の
[calendar]行と、最後のサマリー:[calendar] 2024-01-10 AAPL — SPLIT 4:1 applied to 1 position(s): 100 -> 400 shares (cost basis unchanged; bars stay unadjusted) [calendar] 2024-02-09 AAPL — DIVIDEND $0.2400/share on 400 share(s): +$96.00 cash … [calendar] corporate actions — 1 split(s) applied; 1 dividend(s) applied (0 exact ex-date, 1 estimated +/-7d) - Test Results — 決済済み取引の間に Split または Dividend の行がインラインで表示され(その場合、カードのタイトルは Closed trades & events)、比率または 1 株あたりの金額と、現金への影響が示されます。推定の権利落ち日には
est.が付きます。これらの行にはチャート上の#マーカーはなく、CSV エクスポートからは除外されます。
next_earnings は時点依存
バックテストでは、next_earnings は、今日の時点で計算されたサーバーの「次の決算日」を決して返しません — それは過去のバーに対する先読みになるためです。バー時点で見える直近の決算提出書類と、その企業の開示サイクルから再構築されるため、basis == "filing-cadence" かつ estimated is True となります。
決算の提出書類がまだ見えない場合 — 実行の序盤、または提出履歴がそこまでさかのぼらない銘柄 — は None を返します。常に確認してください。
配当が見えない場合
何も適用されなかった実行は、出力パネルにその理由を表示します。
| ログの内容 | 意味 |
|---|---|
loaded 3/5 symbol(s); 2 without calendar data | 開始時に出力: カレンダーを取得できた銘柄数 |
none of 5 symbol(s) returned calendar data: … | 実行内のどの銘柄にもカレンダーデータがなく、適用できるものがありません |
no calendar data on the server | その銘柄ではカレンダージョブが実行されていません |
calendar has no dividend or split history | 配当なしで、記録された分割もありません |
… ex-dates 2019-05-10..2020-05-08 | 配当はあるが、テストした期間内ではありません |
N with no ex-date, which can never be applied | 履歴はあるが、時間軸上に配置できません |
no positions were held … | アクションの期日に、保有するものがありませんでした |
[calendar] 行がまったく表示されない場合、カレンダーデータが実行にアタッチされていません — Symbol & data タブの Include calendar data のトグルを確認してください。

