diff --git a/__pycache__/strategy.cpython-314.pyc b/__pycache__/strategy.cpython-314.pyc index cf0e366..da2b95e 100644 Binary files a/__pycache__/strategy.cpython-314.pyc and b/__pycache__/strategy.cpython-314.pyc differ diff --git a/__pycache__/trader.cpython-314.pyc b/__pycache__/trader.cpython-314.pyc index eb3309e..600d64c 100644 Binary files a/__pycache__/trader.cpython-314.pyc and b/__pycache__/trader.cpython-314.pyc differ diff --git a/app.py b/app.py index a2b0dda..d50aa41 100644 --- a/app.py +++ b/app.py @@ -69,6 +69,13 @@ def main() -> None: index = 2, ) + st.markdown("### SMA Window") + sma_window = st.selectbox( + "SMA Window", + [5,10,20,50], + index = 0, + ) + # ── Trading Mode ────────────────────────────────── st.markdown("---") st.markdown('
', unsafe_allow_html=True) @@ -127,7 +134,7 @@ def main() -> None: return with st.spinner("Analyzing data..."): - signals, charts, errors, trades, stats = _analyze_cached(tuple(symbols),target_percent,stop_percent,orb_window) + signals, charts, errors, trades, stats = _analyze_cached(tuple(symbols),target_percent,stop_percent,orb_window,sma_window) frame = signals_to_frame(signals) if frame.empty: @@ -367,8 +374,8 @@ def _render_backtest_tab() -> None: @st.cache_data(ttl=CACHE_TTL_SECONDS, show_spinner=False) -def _analyze_cached(symbols: tuple[str, ...],target_percent,stop_percent,orb_window): - return analyze_symbols(list(symbols),target_percent,stop_percent,orb_window) +def _analyze_cached(symbols: tuple[str, ...],target_percent,stop_percent,orb_window,sma_window): + return analyze_symbols(list(symbols),target_percent,stop_percent,orb_window,sma_window) @st.cache_data(ttl=300, show_spinner=False) diff --git a/data/trades.json b/data/trades.json index f666850..ce672b4 100644 --- a/data/trades.json +++ b/data/trades.json @@ -167,13 +167,13 @@ "target": 196.33, "stop_loss": 202.33, "entry_timestamp": "2026-06-10T19:55:00", - "current_price": 200.34, - "status": "OPEN", - "exit_price": null, - "exit_timestamp": null, - "exit_reason": null, - "pnl": 0.0, - "pnl_percent": 0.0 + "current_price": 194.62, + "status": "CLOSED", + "exit_price": 194.62, + "exit_timestamp": "2026-07-02T19:55:00", + "exit_reason": "TARGET", + "pnl": 5.72, + "pnl_percent": 2.86 }, { "id": "4c8c72c174cb", @@ -199,7 +199,23 @@ "target": 278.45, "stop_loss": 283.83, "entry_timestamp": "2026-06-29T19:55:00", - "current_price": 281.63, + "current_price": 308.22, + "status": "CLOSED", + "exit_price": 308.22, + "exit_timestamp": "2026-07-02T19:55:00", + "exit_reason": "STOP_LOSS", + "pnl": -26.59, + "pnl_percent": -9.44 + }, + { + "id": "11a98ecb47fb", + "symbol": "AAPL", + "side": "BUY", + "entry_price": 308.22, + "target": 311.3, + "stop_loss": 306.68, + "entry_timestamp": "2026-07-02T19:55:00", + "current_price": 308.22, "status": "OPEN", "exit_price": null, "exit_timestamp": null, diff --git a/logs/trades.csv b/logs/trades.csv index 2a21ad0..471cb02 100644 --- a/logs/trades.csv +++ b/logs/trades.csv @@ -202,3 +202,15 @@ timestamp,symbol,signal,entry_price,target,stop_loss,last_price,reason 2026-06-29T19:55:00,AAPL,SELL,281.63,278.45,283.83,281.63,Price broke below opening range low with volume confirmation 2026-06-29T19:55:00,AAPL,SELL,281.63,278.17,284.33,281.63,Price broke below opening range low with volume confirmation 2026-06-29T19:55:00,AAPL,SELL,281.63,278.17,284.33,281.63,Price broke below opening range low with volume confirmation +2026-06-29T19:55:00,AAPL,SELL,281.63,276.28,283.04,281.63,Price broke below opening range low with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation +2026-07-02T19:55:00,AAPL,BUY,308.22,311.3,306.68,308.22,Price broke above opening range high with volume confirmation diff --git a/strategy.py b/strategy.py index e055504..7ebe3e7 100644 --- a/strategy.py +++ b/strategy.py @@ -26,7 +26,7 @@ class TradeSignal: reason: str -def calculate_orb_signal(symbol: str, data: pd.DataFrame, timestamp: str, target_percent: float, stop_percent: float, orb_window: int) -> TradeSignal: +def calculate_orb_signal(symbol: str, data: pd.DataFrame, timestamp: str, target_percent: float, stop_percent: float, orb_window: int,sma_window: int) -> TradeSignal: if data.empty: return _hold(symbol, timestamp, "No data available") @@ -58,7 +58,7 @@ def calculate_orb_signal(symbol: str, data: pd.DataFrame, timestamp: str, target current_volume = float(signal_candle["Volume"]) average_volume = float(clean_data["Volume"].iloc[:-1].mean()) if len(clean_data) > 1 else 0.0 volume_confirmed = average_volume > 0 and current_volume > average_volume - sma = _trend_sma(clean_data) + sma = _trend_sma(clean_data,sma_window) buy_trend = last_price > sma sell_trend = last_price < sma breakout_buffer = max(range_high * BREAKOUT_BUFFER_PERCENT, 0.01) @@ -176,11 +176,12 @@ def _opening_range_window(data: pd.DataFrame, orb_window: int) -> pd.DataFrame: return opening_range -def _trend_sma(data: pd.DataFrame) -> float: +def _trend_sma(data: pd.DataFrame, sma_window: int) -> float: close = data["Close"].dropna() + print(f"SMA Window: {sma_window} minutes") if close.empty: return 0.0 - window = min(SMA_WINDOW, len(close)) + window = min(sma_window, len(close)) return float(close.tail(window).mean()) diff --git a/trader.py b/trader.py index 01a0fe3..e6db00d 100644 --- a/trader.py +++ b/trader.py @@ -37,6 +37,7 @@ def analyze_symbols( target_percent: float, stop_percent: float, orb_window: int, + sma_window: int, ) -> tuple[list[TradeSignal], dict[str, pd.DataFrame], dict[str, str], pd.DataFrame, dict[str, float]]: configure_logging() signals: list[TradeSignal] = [] @@ -52,7 +53,7 @@ def analyze_symbols( if result.error: errors[result.symbol or symbol] = result.error - signal = calculate_orb_signal(result.symbol or symbol, result.data, timestamp, target_percent, stop_percent,orb_window) + signal = calculate_orb_signal(result.symbol or symbol, result.data, timestamp, target_percent, stop_percent,orb_window,sma_window) signals.append(signal) if not result.data.empty: