Fix SSL retry logic, add order timeouts, validate position sizes, fix array bounds in crossover detection
This commit is contained in:
1 parent
8c90ff4328
commit
c720ff389d
1 file changed
+66
-25
+66
-25
@@ -300,6 +300,9 @@ def get_bid_ask(symbol):
|
|||||||
|
|
||||||
def submit_market_buy(symbol, position_size):
|
def submit_market_buy(symbol, position_size):
|
||||||
debug_print(f"Submitting market buy order: {symbol}, size=${position_size:.2f}")
|
debug_print(f"Submitting market buy order: {symbol}, size=${position_size:.2f}")
|
||||||
|
if position_size <= 0:
|
||||||
|
debug_print(f"Invalid position size: ${position_size:.2f}")
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
execution_price = api.place_order(symbol, "buy", position_size, None, LIMIT_ORDER_TIMEOUT)
|
execution_price = api.place_order(symbol, "buy", position_size, None, LIMIT_ORDER_TIMEOUT)
|
||||||
if execution_price:
|
if execution_price:
|
||||||
@@ -319,9 +322,17 @@ def submit_market_sell(symbol, qty):
|
|||||||
debug_print(f"Submitting market sell order: {symbol}, qty={qty}")
|
debug_print(f"Submitting market sell order: {symbol}, qty={qty}")
|
||||||
try:
|
try:
|
||||||
shares = int(qty)
|
shares = int(qty)
|
||||||
|
if shares <= 0:
|
||||||
|
debug_print(f"Invalid quantity: {shares}")
|
||||||
|
return None
|
||||||
order = api.submit_order(symbol=symbol, qty=shares, side="sell", type="market", time_in_force="day")
|
order = api.submit_order(symbol=symbol, qty=shares, side="sell", type="market", time_in_force="day")
|
||||||
status = api.get_order(order.id)
|
status = api.get_order(order.id)
|
||||||
|
timeout = 30
|
||||||
|
start_time = time.time()
|
||||||
while status.status not in {"filled", "cancelled", "expired", "rejected"}:
|
while status.status not in {"filled", "cancelled", "expired", "rejected"}:
|
||||||
|
if time.time() - start_time > timeout:
|
||||||
|
debug_print("Order status check timeout")
|
||||||
|
return None
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
status = api.get_order(order.id)
|
status = api.get_order(order.id)
|
||||||
if status.status == "filled":
|
if status.status == "filled":
|
||||||
@@ -336,6 +347,9 @@ def submit_market_sell(symbol, qty):
|
|||||||
|
|
||||||
def submit_limit_buy(symbol, position_size, limit_price):
|
def submit_limit_buy(symbol, position_size, limit_price):
|
||||||
debug_print(f"Submitting limit buy: {symbol}, size=${position_size:.2f}, limit=${limit_price:.2f}")
|
debug_print(f"Submitting limit buy: {symbol}, size=${position_size:.2f}, limit=${limit_price:.2f}")
|
||||||
|
if position_size <= 0:
|
||||||
|
debug_print(f"Invalid position size: ${position_size:.2f}")
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
execution_price = api.place_order(symbol, "buy", position_size, limit_price, LIMIT_ORDER_TIMEOUT)
|
execution_price = api.place_order(symbol, "buy", position_size, limit_price, LIMIT_ORDER_TIMEOUT)
|
||||||
if execution_price:
|
if execution_price:
|
||||||
@@ -360,6 +374,9 @@ def submit_limit_buy(symbol, position_size, limit_price):
|
|||||||
|
|
||||||
def submit_short_sell(symbol, position_size):
|
def submit_short_sell(symbol, position_size):
|
||||||
debug_print(f"Submitting short sell: {symbol}, size=${position_size:.2f}")
|
debug_print(f"Submitting short sell: {symbol}, size=${position_size:.2f}")
|
||||||
|
if position_size <= 0:
|
||||||
|
debug_print(f"Invalid position size: ${position_size:.2f}")
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
execution_price = api.place_order(symbol, "sell", position_size, None, LIMIT_ORDER_TIMEOUT)
|
execution_price = api.place_order(symbol, "sell", position_size, None, LIMIT_ORDER_TIMEOUT)
|
||||||
if execution_price:
|
if execution_price:
|
||||||
@@ -377,6 +394,9 @@ def submit_short_sell(symbol, position_size):
|
|||||||
|
|
||||||
def submit_limit_short_sell(symbol, position_size, limit_price):
|
def submit_limit_short_sell(symbol, position_size, limit_price):
|
||||||
debug_print(f"Submitting limit short: {symbol}, size=${position_size:.2f}, limit=${limit_price:.2f}")
|
debug_print(f"Submitting limit short: {symbol}, size=${position_size:.2f}, limit=${limit_price:.2f}")
|
||||||
|
if position_size <= 0:
|
||||||
|
debug_print(f"Invalid position size: ${position_size:.2f}")
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
execution_price = api.place_order(symbol, "sell", position_size, limit_price, LIMIT_ORDER_TIMEOUT)
|
execution_price = api.place_order(symbol, "sell", position_size, limit_price, LIMIT_ORDER_TIMEOUT)
|
||||||
if execution_price:
|
if execution_price:
|
||||||
@@ -403,9 +423,17 @@ def submit_buy_to_cover(symbol, qty):
|
|||||||
debug_print(f"Submitting buy to cover: {symbol}, qty={qty}")
|
debug_print(f"Submitting buy to cover: {symbol}, qty={qty}")
|
||||||
try:
|
try:
|
||||||
shares = int(qty)
|
shares = int(qty)
|
||||||
|
if shares <= 0:
|
||||||
|
debug_print(f"Invalid quantity: {shares}")
|
||||||
|
return None
|
||||||
order = api.submit_order(symbol=symbol, qty=shares, side="buy", type="market", time_in_force="day")
|
order = api.submit_order(symbol=symbol, qty=shares, side="buy", type="market", time_in_force="day")
|
||||||
status = api.get_order(order.id)
|
status = api.get_order(order.id)
|
||||||
|
timeout = 30
|
||||||
|
start_time = time.time()
|
||||||
while status.status not in {"filled", "cancelled", "expired", "rejected"}:
|
while status.status not in {"filled", "cancelled", "expired", "rejected"}:
|
||||||
|
if time.time() - start_time > timeout:
|
||||||
|
debug_print("Order status check timeout")
|
||||||
|
return None
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
status = api.get_order(order.id)
|
status = api.get_order(order.id)
|
||||||
if status.status == "filled":
|
if status.status == "filled":
|
||||||
@@ -469,23 +497,29 @@ def advanced_signal_generator(symbol):
|
|||||||
|
|
||||||
for i in range(1, CROSSOVER_LOOKBACK + 1):
|
for i in range(1, CROSSOVER_LOOKBACK + 1):
|
||||||
bar_index = current_bar_index - i
|
bar_index = current_bar_index - i
|
||||||
if bar_index >= 1 and (i + 1) < len(short_ma_series):
|
if bar_index >= 1 and bar_index < len(bars) and (bar_index + 1) < len(bars):
|
||||||
if short_ma_series.iloc[-i-1] <= long_ma_series.iloc[-i-1] and short_ma_series.iloc[-i] > long_ma_series.iloc[-i]:
|
idx_current = len(short_ma_series) - i
|
||||||
if bar_index > signal_state.last_bullish_crossover_bar:
|
idx_prev = len(short_ma_series) - i - 1
|
||||||
bullish_crossover = True
|
if idx_prev >= 0 and idx_current < len(short_ma_series):
|
||||||
signal_state.last_bullish_crossover_bar = bar_index
|
if short_ma_series.iloc[idx_prev] <= long_ma_series.iloc[idx_prev] and short_ma_series.iloc[idx_current] > long_ma_series.iloc[idx_current]:
|
||||||
debug_print(f"Bullish crossover detected {i} bars ago")
|
if bar_index > signal_state.last_bullish_crossover_bar:
|
||||||
break
|
bullish_crossover = True
|
||||||
|
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):
|
for i in range(1, CROSSOVER_LOOKBACK + 1):
|
||||||
bar_index = current_bar_index - i
|
bar_index = current_bar_index - i
|
||||||
if bar_index >= 1 and (i + 1) < len(short_ma_series):
|
if bar_index >= 1 and bar_index < len(bars) and (bar_index + 1) < len(bars):
|
||||||
if short_ma_series.iloc[-i-1] >= long_ma_series.iloc[-i-1] and short_ma_series.iloc[-i] < long_ma_series.iloc[-i]:
|
idx_current = len(short_ma_series) - i
|
||||||
if bar_index > signal_state.last_bearish_crossover_bar:
|
idx_prev = len(short_ma_series) - i - 1
|
||||||
bearish_crossover = True
|
if idx_prev >= 0 and idx_current < len(short_ma_series):
|
||||||
signal_state.last_bearish_crossover_bar = bar_index
|
if short_ma_series.iloc[idx_prev] >= long_ma_series.iloc[idx_prev] and short_ma_series.iloc[idx_current] < long_ma_series.iloc[idx_current]:
|
||||||
debug_print(f"Bearish crossover detected {i} bars ago")
|
if bar_index > signal_state.last_bearish_crossover_bar:
|
||||||
break
|
bearish_crossover = True
|
||||||
|
signal_state.last_bearish_crossover_bar = bar_index
|
||||||
|
debug_print(f"Bearish crossover detected {i} bars ago")
|
||||||
|
break
|
||||||
|
|
||||||
rsi_val = rsi(closes, 14).iloc[-1]
|
rsi_val = rsi(closes, 14).iloc[-1]
|
||||||
adx_val = adx(highs, lows, closes).iloc[-1]
|
adx_val = adx(highs, lows, closes).iloc[-1]
|
||||||
@@ -630,7 +664,7 @@ def atr_based_trailing_stop(symbol, entry_price, current_price, initial_stop, po
|
|||||||
|
|
||||||
current_atr = atr(bars['high'], bars['low'], bars['close']).iloc[-1]
|
current_atr = atr(bars['high'], bars['low'], bars['close']).iloc[-1]
|
||||||
|
|
||||||
if current_atr <= 0 or pd.isna(current_atr):
|
if current_atr <= 0 or np.isnan(current_atr):
|
||||||
debug_print(f"Invalid ATR value: {current_atr}, using initial stop")
|
debug_print(f"Invalid ATR value: {current_atr}, using initial stop")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -726,8 +760,17 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"No existing position found or error during recovery: {e}")
|
debug_print(f"No existing position found or error during recovery: {e}")
|
||||||
|
|
||||||
|
retry_count = 0
|
||||||
|
max_retries = 3
|
||||||
|
|
||||||
while clock.is_open:
|
while clock.is_open:
|
||||||
clock = api.get_clock()
|
try:
|
||||||
|
clock = api.get_clock()
|
||||||
|
except Exception as e:
|
||||||
|
debug_print(f"Error fetching clock: {e}")
|
||||||
|
time.sleep(10)
|
||||||
|
continue
|
||||||
|
|
||||||
current_equity = fetch_equity()
|
current_equity = fetch_equity()
|
||||||
drawdown = (opening_equity - current_equity) / opening_equity if opening_equity > 0 else 0
|
drawdown = (opening_equity - current_equity) / opening_equity if opening_equity > 0 else 0
|
||||||
|
|
||||||
@@ -741,10 +784,15 @@ def main():
|
|||||||
|
|
||||||
bars = get_recent_bars(SYMBOL, 10)
|
bars = get_recent_bars(SYMBOL, 10)
|
||||||
if bars is None or len(bars) == 0:
|
if bars is None or len(bars) == 0:
|
||||||
debug_print("No bars available, retrying...")
|
retry_count += 1
|
||||||
|
debug_print(f"No bars available, retry {retry_count}/{max_retries}")
|
||||||
|
if retry_count >= max_retries:
|
||||||
|
debug_print("Max retries reached, continuing with next iteration")
|
||||||
|
retry_count = 0
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
retry_count = 0
|
||||||
current_price = bars['close'].iloc[-1]
|
current_price = bars['close'].iloc[-1]
|
||||||
vix_level = get_vix(api, SYMBOL, USE_VIX_FILTER)
|
vix_level = get_vix(api, SYMBOL, USE_VIX_FILTER)
|
||||||
|
|
||||||
@@ -773,13 +821,6 @@ def main():
|
|||||||
remaining_qty = current_position_qty(SYMBOL)
|
remaining_qty = current_position_qty(SYMBOL)
|
||||||
if remaining_qty == 0:
|
if remaining_qty == 0:
|
||||||
position_active = False
|
position_active = False
|
||||||
if position_type == 'long':
|
|
||||||
trade_pnl = (current_price - entry_price) * 100
|
|
||||||
else:
|
|
||||||
trade_pnl = (entry_price - current_price) * 100
|
|
||||||
total_pnl += trade_pnl
|
|
||||||
logger.info(f"✅ Position closed (PnL: ${trade_pnl:.2f})")
|
|
||||||
debug_print(f"Position fully closed, PnL: ${trade_pnl:.2f}")
|
|
||||||
position_state.reset()
|
position_state.reset()
|
||||||
debug_print(f"Sleeping {seconds_to_human_readable(POLL_INTERVAL)} after exit")
|
debug_print(f"Sleeping {seconds_to_human_readable(POLL_INTERVAL)} after exit")
|
||||||
time.sleep(POLL_INTERVAL)
|
time.sleep(POLL_INTERVAL)
|
||||||
@@ -857,7 +898,7 @@ def main():
|
|||||||
risk_amount = 0
|
risk_amount = 0
|
||||||
|
|
||||||
logger.info(f" Entry=${entry_price:.2f}, Stop=${stop_loss:.2f}, Risk={risk_amount:.2%}")
|
logger.info(f" Entry=${entry_price:.2f}, Stop=${stop_loss:.2f}, Risk={risk_amount:.2%}")
|
||||||
logger.info(f" Regime={regime}, Strength={strength:.2f}, Trade #{trade_count} ({trades_today}/{MAX_TRADES_PER_DAY})")
|
logger.info(f" Regime={regime}, Strength={strength:.2f}, Trade {trade_count} ({trades_today}/{MAX_TRADES_PER_DAY})")
|
||||||
debug_print(f"Trade executed: entry=${entry_price:.2f}, stop=${stop_loss:.2f}, regime={regime}")
|
debug_print(f"Trade executed: entry=${entry_price:.2f}, stop=${stop_loss:.2f}, regime={regime}")
|
||||||
|
|
||||||
position_state.trailing_stop = stop_loss
|
position_state.trailing_stop = stop_loss
|
||||||
|
|||||||
Reference in new issue
Block a user