PR4: Telegram notifications + dip buy below moving average #4

Merged
DasAoD merged 2 commits from feature/telegram-and-dip-buy into main 2026-08-28 20:15:31 +02:00
Owner

Vierter PR. Backtesting ist rausgezogen und wird PR5 (Strategie-Replay über ccxt fetch_ohlcv).

Inhalt

Telegram-Benachrichtigungen ([notify])

  • notifier.notify() POSTet an die Telegram sendMessage-API – stdlib urllib, keine neue Runtime-Abhängigkeit
  • wirft nie: Netzfehler/Timeout werden nur als Warning geloggt, ein fehlgeschlagener Push bricht keinen Buy-Lauf ab
  • Push bei jedem buy- und dip-buy-Lauf, bei dem etwas passiert ist (kein täglicher "0 filled"-Spam)
  • notify.telegram_enabled = true ohne Token und Chat-ID → ConfigError
  • Token steht bauartbedingt im URL-Pfad (/bot<token>/sendMessage), HTTPS, wird nirgends geloggt

Extra-Kauf bei Kurseinbruch ([dip], eigener Befehl + Timer)

  • strategy.simple_moving_average() – ungewichteter Mittelwert aus price_history; None solange < 2 Samples oder Zeitspanne < 3 Tage
  • strategy.execute_dip_run() – kauft je Asset zusätzlich, wenn der aktuelle Kurs dip.threshold_pct % (Default 10) unter der SMA über dip.ma_days Tage (Default 20) liegt
    • höchstens ein Dip-Kauf pro Asset pro ISO-Woche (Periodenschlüssel dip-<jahr>-W<woche>, über den Unique-Index erzwungen)
    • Spend-Cap pro Asset geprüft (opportunistisch: ein teures Asset am Cap blockiert nicht das andere), immer <= safety.max_total_spend
    • note = "dip" am Trade; im Dashboard mit "Dip"-Tag in der Trade-Tabelle
    • standardmäßig aus ([dip] enabled = false) → dip-buy ist dann ein sauberer No-op
  • _buy_one() / _wrong_key_guard() aus execute_buy_run herausgezogen, von beiden Läufen geteilt (kein dupliziertes Fill-/Funds-/Insert-Handling)
  • neuer Subcommand krypto-dca dip-buy
  • deploy/krypto-dca-dip-buy.{service,timer} – oneshot, täglich 09:15 UTC, gleiches Hardening wie der Wochen-Timer

Verifiziert

  • pytest → 55 passed (19 neu): SMA-Mittel/Randfälle, Dip-Trigger + Skip, Wochen-Idempotenz, Cap, disabled, dünne Historie; Telegram disabled/enabled/Netzfehler/fehlende Credentials; [dip]-Validierung; dip-buy-CLI-Smoke
  • End-to-End gegen echte Kraken-Kurse: dip-buy mit SMA künstlich über Markt → beide Assets paper-gefüllt (note=dip, period_key=dip-2026-W35), zweiter Lauf derselben Woche = No-op; regulärer buy und Dip-Kauf koexistieren in derselben Woche über getrennte Periodenschlüssel

Sicherheit

  • Telegram über stdlib-HTTPS, Token nur in config.ini (chmod 600), nicht geloggt
  • Dip-Kauf respektiert max_total_spend, min_quote_balance und den max_quote_balance-Wrong-Key-Guard wie der reguläre Lauf
  • Dip-Timer kann gefahrlos aktiviert werden, bevor [dip] scharf geschaltet wird

Co-authored-by: Claude claude@anthropic.com

Vierter PR. Backtesting ist rausgezogen und wird **PR5** (Strategie-Replay über `ccxt fetch_ohlcv`). ## Inhalt ### Telegram-Benachrichtigungen (`[notify]`) - `notifier.notify()` POSTet an die Telegram `sendMessage`-API &ndash; **stdlib `urllib`**, keine neue Runtime-Abhängigkeit - wirft nie: Netzfehler/Timeout werden nur als Warning geloggt, ein fehlgeschlagener Push bricht keinen Buy-Lauf ab - Push bei jedem `buy`- und `dip-buy`-Lauf, bei dem etwas passiert ist (kein täglicher "0 filled"-Spam) - `notify.telegram_enabled = true` ohne Token **und** Chat-ID &rarr; `ConfigError` - Token steht bauartbedingt im URL-Pfad (`/bot<token>/sendMessage`), HTTPS, wird nirgends geloggt ### Extra-Kauf bei Kurseinbruch (`[dip]`, eigener Befehl + Timer) - `strategy.simple_moving_average()` &ndash; ungewichteter Mittelwert aus `price_history`; `None` solange < 2 Samples oder Zeitspanne < 3 Tage - `strategy.execute_dip_run()` &ndash; kauft je Asset zusätzlich, wenn der aktuelle Kurs `dip.threshold_pct` % (Default 10) unter der SMA über `dip.ma_days` Tage (Default 20) liegt - höchstens **ein Dip-Kauf pro Asset pro ISO-Woche** (Periodenschlüssel `dip-<jahr>-W<woche>`, über den Unique-Index erzwungen) - Spend-Cap **pro Asset** geprüft (opportunistisch: ein teures Asset am Cap blockiert nicht das andere), immer `<= safety.max_total_spend` - `note = "dip"` am Trade; im Dashboard mit "Dip"-Tag in der Trade-Tabelle - standardmäßig **aus** (`[dip] enabled = false`) &rarr; `dip-buy` ist dann ein sauberer No-op - `_buy_one()` / `_wrong_key_guard()` aus `execute_buy_run` herausgezogen, von beiden Läufen geteilt (kein dupliziertes Fill-/Funds-/Insert-Handling) - neuer Subcommand `krypto-dca dip-buy` - `deploy/krypto-dca-dip-buy.{service,timer}` &ndash; oneshot, täglich 09:15 UTC, gleiches Hardening wie der Wochen-Timer ## Verifiziert - `pytest` &rarr; **55 passed** (19 neu): SMA-Mittel/Randfälle, Dip-Trigger + Skip, Wochen-Idempotenz, Cap, disabled, dünne Historie; Telegram disabled/enabled/Netzfehler/fehlende Credentials; `[dip]`-Validierung; `dip-buy`-CLI-Smoke - End-to-End gegen echte Kraken-Kurse: `dip-buy` mit SMA künstlich über Markt &rarr; beide Assets paper-gefüllt (`note=dip`, `period_key=dip-2026-W35`), zweiter Lauf derselben Woche = No-op; regulärer `buy` und Dip-Kauf koexistieren in derselben Woche über getrennte Periodenschlüssel ## Sicherheit - Telegram über stdlib-HTTPS, Token nur in `config.ini` (chmod 600), nicht geloggt - Dip-Kauf respektiert `max_total_spend`, `min_quote_balance` und den `max_quote_balance`-Wrong-Key-Guard wie der reguläre Lauf - Dip-Timer kann gefahrlos aktiviert werden, bevor `[dip]` scharf geschaltet wird Co-authored-by: Claude <claude@anthropic.com>
- notifier.notify() POSTs to the Telegram sendMessage API via stdlib urllib
  (no new runtime dep); never raises, only logs on failure. config rejects
  telegram_enabled without both token and chat_id.
- new [dip] config: enabled (default off), ma_days (20), threshold_pct (10),
  amount_per_buy (0 = reuse strategy.amount_per_buy)
- strategy.simple_moving_average() over price_history; execute_dip_run() buys
  extra when price is >= threshold_pct below the SMA, one buy per asset per ISO
  week (dip-<week> period key), still capped by safety.max_total_spend
- extract _buy_one() / _wrong_key_guard() shared by execute_buy_run and the dip
  run; new `krypto-dca dip-buy` subcommand

Co-authored-by: Claude <claude@anthropic.com>
- deploy: krypto-dca-dip-buy.service + .timer (daily, oneshot, same hardening)
- web: "Dip" tag on dip-note trades in the history table
- config.example.ini: [dip] section, [notify] setup pointer
- README + SETUP: dip-buy + Telegram sections, PR4 marked done, PR5 = backtesting
- tests: SMA + execute_dip_run (trigger, per-week idempotency, cap, disabled,
  thin history), notifier (disabled/enabled/network-error/creds), dip config
  validation, `dip-buy` CLI smoke  -> 55 passed

Co-authored-by: Claude <claude@anthropic.com>
DasAoD merged commit 86daa0372e into main 2026-08-28 20:15:31 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
DasAoD/krypto-dca-bot!4
No description provided.