stock/README.md
2025-08-15 12:19:07 +02:00

7.7 KiB
Raw Blame History

Multi-Asset Portfolio Simulator (Yahoo Finance, Python)

Szybki symulator wielo-aktywny z jedną wspólną kasą.
Działa w pętli co 2 minuty i dla paczki tickerów:

  • pobiera batch danych z Yahoo jednym zapytaniem (yfinance.download),
  • dopina tylko nowe świece (cache ostatniego czasu per ticker),
  • liczy sygnał na close każdej świecy,
  • egzekwuje zlecenie na kolejnym open (bardziej realistycznie),
  • prowadzi portfel (wspólne saldo, SL/TP intrabar, prowizja, poślizg),
  • zapisuje wyniki do dane/ oraz liczy metryki MaxDD, Sharpe, CAGR.

Uwaga: to symulacja oparta o dane z Yahoo. Nie składa prawdziwych zleceń.


Funkcje (skrót)

  • Multi-asset (~20 domyślnych: krypto + forex + złoto GC=F)
  • Batch download (znacznie szybciej niż pojedynczo)
  • Tylko nowe świece (bez pobierania pełnej historii co rundę)
  • Sygnał: EMA200 + SMA(20/50) + RSI(14) + ATR-SL/TP + filtry: MACD, Stochastic, Bollinger, ADX, Supertrend
  • Egzekucja na kolejnym OPEN
  • Portfel: jedna kasa dla wszystkich instrumentów, risk per trade (% equity)
  • Zapisy CSV + portfolio_summary z MaxDD / Sharpe (annual) / CAGR

Wymagania

  • Python 3.9+
  • pip install yfinance pandas numpy

Szybki start

# 1) instalacja
chmod +x install.sh
./install.sh

# 2) uruchomienie (wirtualne środowisko)
source venv/bin/activate
python app.py

# (opcjonalnie w tle)
nohup python app.py > output.log 2>&1 &

Logi lecą do stdout (lub do output.log przy nohup).


Struktura plików

project/
├─ app.py             # główna pętla: batch → nowe świece → decyzje → egzekucja → zapis
├─ config.py          # konfiguracja (tickery, interwał, risk, katalog 'dane', itp.)
├─ data.py            # fetch_batch(): pobieranie paczki tickerów z yfinance
├─ indicators.py      # implementacje wskaźników (SMA/EMA/RSI/ATR/MACD/…)
├─ strategy.py        # evaluate_signal(): logika generowania sygnałów + SL/TP + rpu
├─ portfolio.py       # model portfela: pozycje, pending orders, SL/TP, PnL, equity
├─ metrics.py         # metryki portfelowe: MaxDD, Sharpe (annualized), CAGR
├─ io_utils.py        # zapisy do 'dane/': trades, equity, summary; tworzenie katalogów
├─ requirements.txt   # zależności (yfinance, pandas, numpy)
└─ install.sh         # instalator: venv + pip install -r requirements.txt

Co jest w każdym pliku?

  • config.py
    Definiuje CFG (tickers, interwał, okres pobierania yf_period, minimalna historia, risk, kasa startowa, SL/TP, katalog wyjściowy).
    Zmienisz tu listę instrumentów lub parametry ryzyka.

  • data.py
    fetch_batch(tickers, period, interval) — jedno zapytanie do Yahoo dla wielu tickerów. Zwraca słownik {ticker: DataFrame} z kolumnami open, high, low, close, volume.

  • indicators.py
    Wskaźniki: sma, ema, rsi, atr, macd, stoch_kd, bollinger, adx_val, supertrend.

  • strategy.py
    evaluate_signal(df)Decision(signal, sl, tp, rpu)

    • signal: BUY / SELL / NONE
    • sl/tp: poziomy na bazie ATR i RR
    • rpu (risk per unit): ile ryzyka na jednostkę (do wyliczenia wielkości pozycji)
  • portfolio.py
    Model portfela z jedną kasą:

    • egzekucja na kolejnym OPEN (pending orders),
    • SL/TP intrabar,
    • prowizja i poślizg,
    • portfolio_equity (czas, equity) i lista trades.
  • metrics.py
    Metryki portfela na bazie krzywej equity:

    • Max Drawdown minimalna wartość equity/rolling_max - 1,
    • Sharpe annualized z 1-min zwrotów (525 600 okresów/rok),
    • CAGR roczna złożona stopa wzrostu.
  • io_utils.py
    Tworzy strukturę dane/, zapisuje:

    • dane/portfolio_equity.csv equity w czasie,
    • dane/portfolio_summary.txt JSON z metrykami i statystyką,
    • dane/<TICKER>/<TICKER>_trades.csv dziennik zagrań per instrument.
  • app.py
    Główna pętla:

    1. fetch_batch → nowe świeczki,
    2. dla każdego nowego bara: najpierw egzekucja pending na open, potem sygnał na close i zaplanowanie zlecenia na kolejny open,
    3. zapis CSV + metryki,
    4. pauza do pełnych 2 minut na rundę.

Struktura wyjściowa (w dane/)

dane/
├─ portfolio_equity.csv         # [time(ms), equity, datetime]
├─ portfolio_summary.txt        # JSON z metrykami (MaxDD, Sharpe, CAGR, itp.)
├─ BTC-USD/
│  └─ BTC-USD_trades.csv        # dziennik transakcji dla BTC
├─ ETH-USD/
│  └─ ETH-USD_trades.csv
└─ ...

*_trades.csv (kolumny):
time, datetime, ticker, action(OPEN/CLOSE), side(long/short), price, size, pnl, reason, equity_after


Konfiguracja (najczęściej zmieniane)

Otwórz config.py:

CFG.tickers = ["BTC-USD","ETH-USD","EURUSD=X", ...]  # Twoja lista
CFG.interval = "1m"         # 1m / 2m / 5m / 15m / 30m / 60m / 1h
CFG.yf_period = "2d"        # krótszy = szybciej; dopasuj do interwału
CFG.risk_per_trade = 0.005  # 0.5% equity na trade
CFG.starting_cash = 10000.0 # kasa startowa (w jednostce bazowej)
CFG.sl_atr_mult = 2.0       # ile ATR do SL
CFG.tp_rr = 1.5             # stosunek TP do ryzyka
CFG.root_dir = "dane"       # katalog wyjściowy

Tip

: przy zmianie interwału ustaw odpowiednie yf_period (np. 1m→2d, 5m→10d, 1h→60d), żeby mieć min. ~250 barów do wskaźników.


Jak to działa (timeline 1 świecy)

  1. Nowy bar t przychodzi z Yahoo.
  2. Jeśli był pending order zaplanowany na bar t, otwiera się na jego OPEN.
  3. Jeśli jest otwarta pozycja, sprawdzamy SL/TP intrabar (low/high).
  4. Na CLOSE bara t liczymy sygnał i plan (pending) na OPEN bara t+1.
  5. Snapshot portfelowego equity po close.

Metryki

  • MaxDD: min wartość z (equity/rolling_max - 1).
  • Sharpe (annualized): liczone z 1-min zwrotów pct_change, skalowane przez √(525 600).
    (Brak stopy wolnej od ryzyka/rf ~ 0 w tej wersji.)
  • CAGR: ((equity_end/equity_start)^(1/lata)) - 1.

Uwaga: przy bardzo krótkich danych te metryki mogą być niestabilne.


FAQ

Q: Chcę inne interwały (np. 5m).
A: Zmień CFG.interval = "5m" oraz CFG.yf_period = "10d" (żeby mieć ≥250 barów).

Q: Jak dodać/zmienić tickery?
A: Zedytuj listę w config.py. Dla złota używamy GC=F (futures).

Q: Foldery per ticker nie powstają od razu.
A: Tworzą się na starcie (ensure_dirs). Jeśli jakiś ticker nie ma danych z Yahoo, plik z transakcjami może nie powstać — ale katalog jest.

Q: Wolno działa?
A: Ta wersja używa jednego zapytania na rundę + tylko nowe świece. Dalsze przyspieszenie: rozbij tickery na dwie paczki, jeśli Yahoo dławi się liczbą symboli.

Q: Jak uruchomić jako usługę systemd?
A:

# /etc/systemd/system/portfolio.service
[Unit]
Description=Multi-Asset Portfolio Simulator
After=network.target

[Service]
User=USER
WorkingDirectory=/ścieżka/do/project
ExecStart=/ścieżka/do/project/venv/bin/python /ścieżka/do/project/app.py
Restart=always

[Install]
WantedBy=multi-user.target

Potem:

sudo systemctl daemon-reload
sudo systemctl enable --now portfolio.service
journalctl -u portfolio.service -f

Troubleshooting

  • Yahoo 404 / brak danych dla symbolu → Yahoo czasem zwraca puste dane. Po prostu pomija dany ticker w tej rundzie.
  • Za mało świec (history_min_bars) → zwiększ yf_period.
  • Błędy czasu → wymuszamy UTC; jeśli masz własne źródło, ujednolicaj strefę.
  • Sharpe = 0 → zbyt krótki okres lub zerowa zmienność w danych (rzadkie).

Licencja

Ten kod jest przykładowy/edukacyjny; używaj na własną odpowiedzialność. Nie stanowi porady inwestycyjnej.