stock/app.py
2025-08-15 12:19:07 +02:00

77 lines
2.8 KiB
Python

from __future__ import annotations
import time
from typing import Dict
import pandas as pd
from config import CFG
from data import fetch_batch
from strategy import evaluate_signal
from portfolio import Portfolio
from io_utils import ensure_dirs, save_outputs
def interval_to_timedelta(interval: str) -> pd.Timedelta:
# prosta mapka dla 1m/2m/5m/15m/30m/60m/1h
mapping = {
"1m":"1min","2m":"2min","5m":"5min","15m":"15min","30m":"30min",
"60m":"60min","90m":"90min","1h":"60min"
}
key = mapping.get(interval, "1min")
return pd.to_timedelta(key)
if __name__ == "__main__":
ensure_dirs(CFG.root_dir, CFG.tickers)
portfolio = Portfolio(starting_cash=CFG.starting_cash, commission_per_trade=1.0, slippage_bp=1.0)
last_ts: Dict[str, pd.Timestamp] = {}
hist: Dict[str, pd.DataFrame] = {}
bar_delta = interval_to_timedelta(CFG.interval)
while True:
round_t0 = time.time()
batch = fetch_batch(CFG.tickers, CFG.yf_period, CFG.interval)
for tk, df in batch.items():
if df.empty:
continue
df = df.copy()
df.index = pd.to_datetime(df.index, utc=True)
prev = hist.get(tk)
if prev is not None and not prev.empty:
df_all = pd.concat([prev, df[~df.index.isin(prev.index)]], axis=0).sort_index()
else:
df_all = df.sort_index()
hist[tk] = df_all.tail(2000)
last = last_ts.get(tk)
new_part = df_all[df_all.index > last] if last is not None else df_all
if not new_part.empty:
for ts, row in new_part.iterrows():
o,h,l,c = float(row["open"]), float(row["high"]), float(row["low"]), float(row["close"])
# 1) egzekucja oczekujących na OPEN tego baraz
portfolio.on_new_bar(tk, ts, o,h,l,c)
# 2) sygnał na CLOSE → plan na KOLEJNY OPEN
df_upto = hist[tk].loc[:ts]
dec = evaluate_signal(df_upto)
portfolio.schedule_order(
tk, dec.signal, dec.rpu, dec.sl, dec.tp,
next_bar_ts=ts + pd.to_timedelta(1, unit="min"),
ref_price=float(df_upto["close"].iloc[-1])
)
last_ts[tk] = new_part.index[-1]
# zapis
import pandas as pd
trades_df = pd.DataFrame(portfolio.trades)
eq_df = pd.DataFrame(portfolio.portfolio_equity, columns=["time","equity"])
save_outputs(CFG.root_dir, CFG.tickers, trades_df, eq_df, portfolio.cash)
elapsed = time.time() - round_t0
sleep_s = max(0, 120 - elapsed)
print(f"Runda OK ({elapsed:.1f}s). Pauza {sleep_s:.1f}s.")
print(sleep_s)
time.sleep(sleep_s)