NIFTY
NIFTY₹24,812.40+0.49%
SENSEX
SENSEX₹81,340.25+0.38%
HDFCBANK
HDFCBANK₹1,724.80+3.42%
RELIANCE
RELIANCE₹2,980.50+2.20%
INFY
INFY₹1,856.30+4.15%
TCS
TCS₹4,214.00+1.85%
SUNPHARMA
SUNPHARMA₹1,768.20-2.63%
ICICIBANK
ICICIBANK₹1,218.40+0.21%
TATAMOTORS
TATAMOTORS₹1,086.50+5.60%
ITC
ITC₹512.75+7.80%
NIFTY
NIFTY₹24,812.40+0.49%
SENSEX
SENSEX₹81,340.25+0.38%
HDFCBANK
HDFCBANK₹1,724.80+3.42%
RELIANCE
RELIANCE₹2,980.50+2.20%
INFY
INFY₹1,856.30+4.15%
TCS
TCS₹4,214.00+1.85%
SUNPHARMA
SUNPHARMA₹1,768.20-2.63%
ICICIBANK
ICICIBANK₹1,218.40+0.21%
TATAMOTORS
TATAMOTORS₹1,086.50+5.60%
ITC
ITC₹512.75+7.80%
Project Rho/
Strategy RepositoryActive
branch: mainclean
Commit History
S

feat: add dynamic position sizing

sachinsharma·2 hours ago
S

fix: handle edge case in rsi calculation

sachinsharma·5 hours ago
S

refactor: split strategy logic

sachinsharma·1 day ago
S

feat: add backtest configuration

sachinsharma·2 days ago
S

initial commit

sachinsharma·3 days ago
Your code runs in a secure sandbox. No real money. No broker access.
rsi_strategy.py
indicators.py
risk_manager.py
14px
src/strategy>rsi_strategy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import pandas as pd
import numpy as np
from .indicators import calculate_rsi, calculate_ema, calculate_atr
from .risk_manager import get_position_size, calculate_trailing_stop
class RSIMomentumStrategy:
"""
RSI + Moving Average Momentum strategy for Indian Equities.
- Entry Long: RSI < oversold threshold and price > 50-period EMA
- Exit Long: RSI > overbought threshold or trailing stop breach
- Dynamic volatility sizing via ATR risk model
"""
def __init__(self,
rsi_period: int = 14,
ma_period: int = 50,
rsi_oversold: float = 30.0,
rsi_overbought: float = 70.0,
risk_per_trade: float = 0.02,
max_slippage_bps: float = 4.5):
self.rsi_period = rsi_period
self.ma_period = ma_period
self.rsi_oversold = rsi_oversold
self.rsi_overbought = rsi_overbought
self.risk_per_trade = risk_per_trade
self.max_slippage_bps = max_slippage_bps
self.current_position = 0.0
self.entry_price = 0.0
def generate_signals(self, df: pd.DataFrame) -> pd.DataFrame:
"""
Generates vectorized discrete signals for offline backtesting.
"""
df = df.copy()
df['rsi'] = calculate_rsi(df['close'], self.rsi_period)
df['ema'] = calculate_ema(df['close'], self.ma_period)
df['atr'] = calculate_atr(df, period=14)
df['signal'] = 0
long_condition = (df['rsi'] < self.rsi_oversold) & (df['close'] > df['ema'])
short_condition = (df['rsi'] > self.rsi_overbought) | (df['close'] < df['ema'])
df.loc[long_condition, 'signal'] = 1
df.loc[short_condition, 'signal'] = -1
return df
def on_candle_close(self, candle: dict, account_equity: float) -> dict:
"""
Event-driven execution handler called on every bar close.
"""
price = candle['close']
rsi = candle['rsi']
ema = candle['ema']
atr = candle.get('atr', 2.5)
# Evaluate Long Entry
if self.current_position == 0:
if rsi < self.rsi_oversold and price > ema:
size = get_position_size(account_equity, price, atr, self.risk_per_trade)
self.current_position = size
self.entry_price = price
return {
"action": "BUY",
"quantity": size,
"limit_price": price,
"stop_loss": price - (2.0 * atr),
"target": price + (4.0 * atr)
}
# Evaluate Long Exit
elif self.current_position > 0:
trailing_stop = calculate_trailing_stop(self.entry_price, price, atr)
if rsi > self.rsi_overbought or price < trailing_stop:
qty = self.current_position
self.current_position = 0
return {
"action": "SELL",
"quantity": qty,
"limit_price": price,
"reason": "RSI_EXIT" if rsi > self.rsi_overbought else "TRAILING_STOP"
}
return {"action": "HOLD"}
Sandbox Environment
Allowed commands:
(sandbox) $ python -V
Python 3.11.7
(sandbox) $ pip install -r requirements.txt
Requirement already satisfied: pandas in /sandbox/venv/lib/python3.11/site-packages (2.2.3)
Requirement already satisfied: numpy in /sandbox/venv/lib/python3.11/site-packages (1.26.4)
(sandbox) $ python src/strategy/rsi_strategy.py --test
Running strategy backtest (local data)...
Backtest completed. Total trades: 42 | Win rate: 52.4% | Final PnL: +8.7%
(sandbox) $
Compare Changes2 files changed
rsi_strategy.py
main (current)
1 import pandas as pd
2 import numpy as np
3 from .indicators import calculate_rsi
4 - from .risk_manager import get_position_size
...
11 class RSIMomentumStrategy:
14 def __init__(self, rsi_period=14,
15 ma_period=50,
16 rsi_oversold=30,
18 - risk_per_trade=0.02):
feature/dynamic-sizing
1 import pandas as pd
2 import numpy as np
3 from .indicators import calculate_rsi
4 from .risk_manager import get_position_size
5 + from .utils.helpers import get_current_volatility
...
11 class RSIMomentumStrategy:
14 def __init__(self, rsi_period=14,
15 ma_period=50,
16 rsi_oversold=30,
18 + risk_per_trade=0.02,
19 + use_dynamic_sizing=True):
> 2 files changed+12-4

Ready for review

Please approve, reject or request changes before applying these modifications.

Quick File & Strategy Jump

Search repo files, safe terminal commands, and strategy branches...