| .idea | ||
| new | ||
| static | ||
| templates | ||
| app.py | ||
| config.py | ||
| data.py | ||
| indicators.py | ||
| install.sh | ||
| io_utils.py | ||
| metrics.py | ||
| portfolio.py | ||
| pythonProject.zip | ||
| README.md | ||
| requirements.txt | ||
| server.py | ||
| strategy.py | ||
| trader.py | ||
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
DefiniujeCFG(tickers, interwał, okres pobieraniayf_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 kolumnamiopen, 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)
- signal:
-
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 listatrades.
-
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.
- Max Drawdown – minimalna wartość
-
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:fetch_batch→ nowe świeczki,- dla każdego nowego bara: najpierw egzekucja pending na open, potem sygnał na close i zaplanowanie zlecenia na kolejny open,
- zapis CSV + metryki,
- 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)
- Nowy bar
tprzychodzi z Yahoo. - Jeśli był pending order zaplanowany na bar
t, otwiera się na jego OPEN. - Jeśli jest otwarta pozycja, sprawdzamy SL/TP intrabar (
low/high). - Na CLOSE bara
tliczymy sygnał i plan (pending) na OPEN barat+1. - 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.