Fix critical bugs: RSI division by zero, API price validation, order timeout, and crossover race condition
This commit is contained in:
@@ -64,7 +64,7 @@ class AlpacaClient:
|
||||
price_source = limit_price
|
||||
else:
|
||||
price_source = bid_price if side == "buy" else ask_price
|
||||
if price_source is None:
|
||||
if price_source is None or price_source <= 0:
|
||||
return None
|
||||
shares = int(notional / price_source)
|
||||
if shares == 0:
|
||||
@@ -83,7 +83,11 @@ class AlpacaClient:
|
||||
return None
|
||||
order = self.submit_order(symbol=symbol, qty=shares, side=side, type="market", time_in_force="day")
|
||||
status = self.get_order(order.id)
|
||||
timeout = 30
|
||||
start_time = time.time()
|
||||
while status.status not in {"filled", "cancelled", "expired", "rejected"}:
|
||||
if time.time() - start_time > timeout:
|
||||
return None
|
||||
time.sleep(0.5)
|
||||
status = self.get_order(order.id)
|
||||
if status.status == "filled":
|
||||
|
||||
+16
-13
@@ -206,6 +206,17 @@ api = AlpacaClient(
|
||||
api_version='v2'
|
||||
)
|
||||
|
||||
class SignalState:
|
||||
def __init__(self):
|
||||
self.last_bullish_crossover_bar = -999
|
||||
self.last_bearish_crossover_bar = -999
|
||||
|
||||
def reset(self):
|
||||
self.last_bullish_crossover_bar = -999
|
||||
self.last_bearish_crossover_bar = -999
|
||||
|
||||
signal_state = SignalState()
|
||||
|
||||
def debug_print(message):
|
||||
if DEBUG_MODE:
|
||||
debug_logger.debug(f"🔎 {message}")
|
||||
@@ -426,28 +437,23 @@ def advanced_signal_generator(symbol):
|
||||
bearish_crossover = False
|
||||
|
||||
if REQUIRE_MA_CROSSOVER and len(bars) >= LONG_WINDOW + CROSSOVER_LOOKBACK:
|
||||
if not hasattr(advanced_signal_generator, 'last_bullish_crossover_bar'):
|
||||
advanced_signal_generator.last_bullish_crossover_bar = -999
|
||||
if not hasattr(advanced_signal_generator, 'last_bearish_crossover_bar'):
|
||||
advanced_signal_generator.last_bearish_crossover_bar = -999
|
||||
|
||||
current_bar_index = len(bars) - 1
|
||||
|
||||
for i in range(1, CROSSOVER_LOOKBACK + 1):
|
||||
bar_index = current_bar_index - i
|
||||
if short_ma_series.iloc[-i-1] <= long_ma_series.iloc[-i-1] and short_ma_series.iloc[-i] > long_ma_series.iloc[-i]:
|
||||
if bar_index > advanced_signal_generator.last_bullish_crossover_bar:
|
||||
if bar_index > signal_state.last_bullish_crossover_bar:
|
||||
bullish_crossover = True
|
||||
advanced_signal_generator.last_bullish_crossover_bar = bar_index
|
||||
signal_state.last_bullish_crossover_bar = bar_index
|
||||
debug_print(f"Bullish crossover detected {i} bars ago")
|
||||
break
|
||||
|
||||
for i in range(1, CROSSOVER_LOOKBACK + 1):
|
||||
bar_index = current_bar_index - i
|
||||
if short_ma_series.iloc[-i-1] >= long_ma_series.iloc[-i-1] and short_ma_series.iloc[-i] < long_ma_series.iloc[-i]:
|
||||
if bar_index > advanced_signal_generator.last_bearish_crossover_bar:
|
||||
if bar_index > signal_state.last_bearish_crossover_bar:
|
||||
bearish_crossover = True
|
||||
advanced_signal_generator.last_bearish_crossover_bar = bar_index
|
||||
signal_state.last_bearish_crossover_bar = bar_index
|
||||
debug_print(f"Bearish crossover detected {i} bars ago")
|
||||
break
|
||||
|
||||
@@ -647,10 +653,7 @@ def main():
|
||||
trades_today = 0
|
||||
total_pnl = 0
|
||||
|
||||
if hasattr(advanced_signal_generator, 'last_bullish_crossover_bar'):
|
||||
delattr(advanced_signal_generator, 'last_bullish_crossover_bar')
|
||||
if hasattr(advanced_signal_generator, 'last_bearish_crossover_bar'):
|
||||
delattr(advanced_signal_generator, 'last_bearish_crossover_bar')
|
||||
signal_state.reset()
|
||||
|
||||
try:
|
||||
existing_position = api.get_position(SYMBOL)
|
||||
|
||||
@@ -10,7 +10,8 @@ def rsi(data, window=14):
|
||||
delta = data.diff()
|
||||
gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
|
||||
loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
|
||||
loss = loss.replace(0, 0.0001)
|
||||
loss = loss.replace(0, 1e-10)
|
||||
loss = loss.clip(lower=1e-10)
|
||||
rs = gain / loss
|
||||
rsi_val = 100 - (100 / (1 + rs))
|
||||
return rsi_val
|
||||
|
||||
Reference in New Issue
Block a user