Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified __pycache__/strategy.cpython-314.pyc
Binary file not shown.
Binary file modified __pycache__/trader.cpython-314.pyc
Binary file not shown.
13 changes: 10 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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('<div class="sidebar-header">TRADING MODE</div>', unsafe_allow_html=True)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
32 changes: 24 additions & 8 deletions data/trades.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions logs/trades.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 5 additions & 4 deletions strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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())


Expand Down
3 changes: 2 additions & 1 deletion trader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = []
Expand All @@ -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:
Expand Down