Add initial implementation of backtesting framework with CLI interface. Introduce core modules for data loading, trade management, performance metrics, and logging. Include Supertrend indicator calculations and slippage estimation. Update .gitignore to exclude logs and CSV files.
This commit is contained in:
3
indicators/__init__.py
Normal file
3
indicators/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .supertrend import add_supertrends, compute_meta_trend
|
||||
|
||||
__all__ = ["add_supertrends", "compute_meta_trend"]
|
||||
58
indicators/supertrend.py
Normal file
58
indicators/supertrend.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _atr(high: pd.Series, low: pd.Series, close: pd.Series, period: int) -> pd.Series:
|
||||
hl = (high - low).abs()
|
||||
hc = (high - close.shift()).abs()
|
||||
lc = (low - close.shift()).abs()
|
||||
tr = pd.concat([hl, hc, lc], axis=1).max(axis=1)
|
||||
return tr.rolling(period, min_periods=period).mean()
|
||||
|
||||
|
||||
def supertrend_series(df: pd.DataFrame, length: int, multiplier: float) -> pd.Series:
|
||||
atr = _atr(df["High"], df["Low"], df["Close"], length)
|
||||
hl2 = (df["High"] + df["Low"]) / 2
|
||||
upper = hl2 + multiplier * atr
|
||||
lower = hl2 - multiplier * atr
|
||||
|
||||
trend = pd.Series(index=df.index, dtype=float)
|
||||
dir_up = True
|
||||
prev_upper = np.nan
|
||||
prev_lower = np.nan
|
||||
|
||||
for i in range(len(df)):
|
||||
if i == 0 or pd.isna(atr.iat[i]):
|
||||
trend.iat[i] = np.nan
|
||||
prev_upper = upper.iat[i]
|
||||
prev_lower = lower.iat[i]
|
||||
continue
|
||||
|
||||
cu = min(upper.iat[i], prev_upper) if dir_up else upper.iat[i]
|
||||
cl = max(lower.iat[i], prev_lower) if not dir_up else lower.iat[i]
|
||||
|
||||
if df["Close"].iat[i] > cu:
|
||||
dir_up = True
|
||||
elif df["Close"].iat[i] < cl:
|
||||
dir_up = False
|
||||
|
||||
prev_upper = cu if dir_up else upper.iat[i]
|
||||
prev_lower = lower.iat[i] if dir_up else cl
|
||||
trend.iat[i] = cl if dir_up else cu
|
||||
|
||||
return trend
|
||||
|
||||
|
||||
def add_supertrends(df: pd.DataFrame, settings: list[tuple[int, float]]) -> pd.DataFrame:
|
||||
out = df.copy()
|
||||
for length, mult in settings:
|
||||
col = f"supertrend_{length}_{mult}"
|
||||
out[col] = supertrend_series(out, length, mult)
|
||||
out[f"bull_{length}_{mult}"] = (out["Close"] >= out[col]).astype(int)
|
||||
return out
|
||||
|
||||
|
||||
def compute_meta_trend(df: pd.DataFrame, settings: list[tuple[int, float]]) -> pd.Series:
|
||||
bull_cols = [f"bull_{l}_{m}" for l, m in settings]
|
||||
return (df[bull_cols].sum(axis=1) == len(bull_cols)).astype(int)
|
||||
Reference in New Issue
Block a user