PagesDonnées de calendrier · 13 / 29
Module de calendrier
Le module de calendrier donne à votre stratégie l'historique des dividendes, l'historique des fractionnements, les dates de résultats, la date d'introduction en bourse et les dépôts SEC récents d'une société — et permet au backtest d'appliquer automatiquement les fractionnements et dividendes à vos positions.
Activez Include calendar data dans l'onglet Symbol & data de la fenêtre Run backtest. Il est activé par défaut, et votre choix (ainsi que les deux sous-options) est mémorisé pour l'exécution suivante. Les calendriers se chargent automatiquement pour chaque symbole négocié lors de l'exécution, y compris un univers résolu par un screener — il n'y a pas de sélecteur par symbole. La fenêtre Test d'un agent propose la même option — Include calendar data (dividends, splits) (voir Agents).
Backtests uniquement. Les données de calendrier sont chargées pour les backtests, Debug Test et les tests d'agents. Les exécutions forward — chart forward tests, exécutions bulk d'AutoTrading et QuantCloud — ne reçoivent jamais de calendrier ; calendar y vaut donc toujours None.
Pourquoi c'est important : les barres de prix sont brutes
Les bougies d'un backtest sont non ajustées. Sans données de calendrier :
- Un fractionnement 4 pour 1 ressemble à un effondrement de 75 % du prix en une nuit, et votre position simulée s'effondre avec lui.
- Les dividendes n'arrivent jamais, ce qui sous-estime discrètement le rendement total de toute position détenue longtemps — environ 2 %/an pour une société versant des dividendes classique.
Les deux sous-options corrigent les deux problèmes sans aucune modification du code.
Le paramètre de rappel calendar
Ajoutez un paramètre calendar à n'importe quel rappel et la référence vous est transmise :
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
...Fonctionne avec on_bar, on_tick et on_timer. L'argument calendar est associé par son nom ; un script sans paramètre calendar se comporte donc exactement comme avant, et un calendar déclaré reçoit soit la référence, soit None — jamais un autre objet, quoi que prenne d'autre votre signature. Si vous lisez aussi des données fondamentales, la signature recommandée est def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None).
Vous pouvez aussi accéder à la même référence sans paramètre : la variable globale de script qc_calendar, ou quantcraft.process.runtime.qc_calendar.
Méthodes
| Méthode | Renvoie |
|---|---|
dividends(bar_time, symbol=None) | Les dividendes publics à cette barre |
splits(bar_time, symbol=None) | Les fractionnements annoncés à cette barre |
filings(bar_time, symbol=None) | Les dépôts SEC publics à cette barre |
next_earnings(bar_time, symbol=None) | {date, basis, estimated, …} ou None |
days_to_earnings(bar_time, symbol=None) | int ou None |
ipo_date(symbol=None) | date ou None |
current(bar_time, symbol=None) | Un dictionnaire instantané de tout ce qui précède à cette barre, ou None |
dividends_between(start, end, symbol=None) | Les dividendes dont la date ex-dividende tombe dans (start, end] |
splits_between(start, end, symbol=None) | Les fractionnements dont la date d'effet tombe dans (start, end] |
has(symbol=None) | Indique si ce symbole a des données de calendrier |
symbols / primary_symbol() / get(symbol=None) | Les symboles chargés, celui par défaut, et le calendrier brut par symbole (ou None) |
Les méthodes _between utilisent les dates d'effet (« quand cela touche-t-il ma position ? »), contrairement aux méthodes à heure de barre ci-dessus, qui utilisent les dates « aurais-je pu le savoir ? » — voir la section suivante.
bar_time accepte bar["t"], bar.t[0], un datetime, une date ou des secondes epoch.
Les listes sont classées de la plus ancienne à la plus récente — dividends(...)[-1] est la plus récente. C'est l'inverse des données fondamentales, où l'indice 0 est la période la plus récente.
Un symbole sans données de calendrier renvoie [] ou None, jamais une erreur. La plupart des symboles hors grandes capitalisations n'ont pas de calendrier sur le serveur ; testez donc la vacuité plutôt que d'attendre des exceptions.
Deux dates par événement — utilisez la bonne
Chaque dividende et chaque fractionnement porte deux dates, et choisir la mauvaise introduit un biais d'anticipation :
| « Aurais-je pu le savoir ? » | « Quand cela affecte-t-il ma position ? » | |
|---|---|---|
| Dividende | declaration_date | ex_date |
| Fractionnement | filing_date | effective_date |
dividends() / splits() / filings() filtrent sur la première colonne — ils ne renvoient que ce qui était public à votre barre. Un fractionnement est souvent visible des semaines avant son entrée en vigueur, car le 8-K est déposé à l'avance :
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 effectiveChamps des événements
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 (dividendes) et effective_date (fractionnements) peuvent valoir None — testez avant de comparer.
La category d'un dépôt est l'une des suivantes : earnings, acquisition, officer-director, charter-amendment, agreement, regulation-fd, auditor-change, shareholder-vote, cybersecurity, other.
L'indicateur estimated
EDGAR ne publie pas les dates ex-dividende. Sauf si des données de la bourse étaient disponibles, la date ex-dividende est estimée à la date de déclaration + 10 jours et est exacte à environ ±7 jours, avec estimated is True. Par défaut, la simulation crédite quand même les dividendes estimés (politique best_available) ; un préréglage d'exécution (.qcs) peut définir dividendDatePolicy sur exact_only (ignorer les estimés) ou off — il n'existe aucun contrôle dans la fenêtre pour cela. Filtrez dessus dans votre propre logique si votre stratégie est sensible à la date ex-dividende :
exact = [d for d in calendar.dividends(bar["t"], symbol) if not d.estimated]Opérations sur titres dans la simulation
Les deux sous-options sont activées par défaut lorsque les données de calendrier le sont, et toutes deux s'exécutent avant vos rappels à chaque barre — on_bar voit donc toujours une position déjà ajustée.
Ajuster les positions pour les fractionnements d'actions — à la date d'effet, le nombre d'actions est multiplié par le ratio et le prix de revient divisé par celui-ci. Les prix de stop et d'objectif sont également remis à l'échelle. Comme qty × entry_price est inchangé, votre courbe de capital reste continue à travers le fractionnement.
Les barres de prix restent volontairement non ajustées ; bar["close"] est donc le véritable prix historique. Un indicateur calculé sur la série brute de clôtures verra toujours l'écart du fractionnement — ajustez votre propre série avec calendar.splits(...) si cela importe.
Créditer les dividendes en espèces — à la date ex-dividende, qty × amount est ajouté aux espèces pour les positions longues et retranché pour les positions courtes (un vendeur à découvert doit le dividende au prêteur). Cela alimente le capital et toutes les métriques de rendement, mais pas realized_pnl, qui reste limité aux trades. Lisez les totaux dans les métriques du compte :
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"])Où voir les opérations sur titres
Rien ne modifie silencieusement votre position ni vos espèces :
- Panneau de sortie — une ligne
[calendar]par opération appliquée, plus une synthèse à la fin :[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 — une ligne Split ou Dividend apparaît parmi les trades clôturés (la carte s'intitule alors Closed trades & events), avec le ratio ou le montant par action et l'impact en espèces. Une date ex-dividende estimée est marquée
est.Ces lignes n'ont pas de marqueur#sur le graphique et sont exclues de l'export CSV.
next_earnings est à un instant donné
Dans un backtest, next_earnings ne renvoie jamais la « prochaine date de résultats » du serveur calculée à aujourd'hui — ce serait un biais d'anticipation sur une barre historique. Elle est reconstituée à partir du dernier dépôt de résultats visible à votre barre et de la cadence de publication de la société ; ainsi basis == "filing-cadence" et estimated is True.
Elle renvoie None lorsqu'aucun dépôt de résultats n'est encore visible — en début d'exécution, ou pour un symbole dont l'historique de dépôts ne remonte pas si loin. Testez-le toujours.
Quand vous ne voyez aucun dividende
Une exécution qui n'applique rien en donne la raison dans le panneau de sortie :
| Le journal indique | Signification |
|---|---|
loaded 3/5 symbol(s); 2 without calendar data | Affiché au début : combien de symboles ont obtenu un calendrier |
none of 5 symbol(s) returned calendar data: … | Aucun symbole de l'exécution n'a de données de calendrier — rien ne peut s'appliquer |
no calendar data on the server | La tâche de calendrier n'a pas été exécutée pour ce symbole |
calendar has no dividend or split history | Ne verse pas de dividendes, aucun fractionnement enregistré |
… ex-dates 2019-05-10..2020-05-08 | Il verse des dividendes, mais pas dans votre plage de dates testée |
N with no ex-date, which can never be applied | L'historique existe mais ne peut pas être placé sur l'horloge |
no positions were held … | Rien n'était ouvert quand une opération est arrivée à échéance |
Si aucune ligne [calendar] n'apparaît, les données de calendrier n'ont pas été jointes à l'exécution — vérifiez la bascule Include calendar data dans l'onglet Symbol & data.
Voir aussi
- Backtests — la fenêtre Run backtest et l'option Include calendar data
- Cycle de vie d'une stratégie — paramètre de rappel
calendar, variable globale d'exécutionqc_calendar - Modèle de compte — où atterrissent les espèces de dividendes et les ajustements de fractionnements
- Screener — comment les calendriers se chargent lorsqu'un screener résout la liste de symboles
- Résultats des tests — lignes Split / Dividend dans le tableau des trades clôturés
- Panneau de sortie — lignes de journal
[calendar]

