Documentation1.0 (latest)
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éthodeRenvoie
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 ? »
Dividendedeclaration_dateex_date
Fractionnementfiling_dateeffective_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 effective

Champs 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, source

amount (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 indiqueSignification
loaded 3/5 symbol(s); 2 without calendar dataAffiché 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 serverLa tâche de calendrier n'a pas été exécutée pour ce symbole
calendar has no dividend or split historyNe verse pas de dividendes, aucun fractionnement enregistré
… ex-dates 2019-05-10..2020-05-08Il verse des dividendes, mais pas dans votre plage de dates testée
N with no ex-date, which can never be appliedL'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écution qc_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]
Données de calendrier — Documentation (1.0 (latest)) | QuantCraft