Fix missing trade logging for profit targets, max hold time, and EOD closes

This commit is contained in:
Justin Oros
2026-02-05 10:37:13 -07:00
parent d90ad33961
commit a84725c575
2 changed files with 167 additions and 22 deletions
+7 -7
View File
@@ -17,12 +17,12 @@
"ENABLE_SLIPPAGE": true,
"SLIPPAGE_PCT": 0.0005,
"COMMISSION_PCT": 0.0005,
"MIN_SIGNAL_STRENGTH": 0.5,
"MIN_SIGNAL_STRENGTH": 0.4,
"BACKTEST_DAYS": 90,
"USE_LIMIT_ORDERS": false,
"LIMIT_ORDER_TIMEOUT": 60,
"ADX_THRESHOLD": 30,
"VOLUME_MULTIPLIER": 1.0,
"VOLUME_MULTIPLIER": 0.7,
"ATR_STOP_MULTIPLIER": 2.5,
"MAX_HOLD_TIME": 3600,
"REGIME_DETECTION": true,
@@ -35,19 +35,19 @@
"VIX_THRESHOLD": 30,
"USE_VIX_FILTER": false,
"USE_FIBONACCI": false,
"MAX_TRADES_PER_DAY": 1,
"MAX_TRADES_PER_DAY": 3,
"SKIP_MONDAYS_FRIDAYS": false,
"USE_200_SMA_FILTER": false,
"REQUIRE_MACD_CONFIRMATION": true,
"REQUIRE_MACD_CONFIRMATION": false,
"MIN_RISK_REWARD": 2.0,
"PULLBACK_PERCENTAGE": 0.382,
"ENABLE_SHORT_SELLING": true,
"RSI_BUY_MAX": 55,
"RSI_SELL_MIN": 45,
"RSI_BUY_MAX": 65,
"RSI_SELL_MIN": 35,
"RSI_SELL_MAX": 70,
"RSI_RANGE_OVERSOLD": 30,
"RSI_RANGE_OVERBOUGHT": 70,
"REQUIRE_MA_CROSSOVER": true,
"REQUIRE_MA_CROSSOVER": false,
"CROSSOVER_LOOKBACK": 3,
"REQUIRE_CASH_ACCOUNT": false,
"T1_SETTLEMENT_ENABLED": false,
+160 -15
View File
@@ -969,10 +969,11 @@ def scale_out_profit_taking(symbol, entry_price, current_price, stop_loss, posit
half_qty = int(qty / 2)
if half_qty > 0:
debug_print(f"Target 1 hit ({target_1_pct:.2f}%), scaling out {half_qty} shares")
exit_price = None
if position_type == 'long':
submit_market_sell(symbol, half_qty)
exit_price = submit_market_sell(symbol, half_qty)
else:
submit_buy_to_cover(symbol, half_qty)
exit_price = submit_buy_to_cover(symbol, half_qty)
position_state.target_1_hit = True
logger.info(f"💰 Partial profit @ {profit_pct:.2f}% ({half_qty} shares)")
debug_print(f"Partial profit taken: {half_qty} shares @ {profit_pct:.2f}%")
@@ -985,15 +986,16 @@ def scale_out_profit_taking(symbol, entry_price, current_price, stop_loss, posit
qty = current_position_qty(symbol)
if qty != 0:
debug_print(f"Target 2 hit ({target_2_pct:.2f}%), closing remaining {qty} shares")
exit_price = None
if position_type == 'long':
submit_market_sell(symbol, qty)
exit_price = submit_market_sell(symbol, qty)
else:
submit_buy_to_cover(symbol, qty)
exit_price = submit_buy_to_cover(symbol, qty)
logger.info(f"💰💰 Full profit @ {profit_pct:.2f}%")
debug_print(f"Full profit target hit: closed @ {profit_pct:.2f}%")
return True
return True, exit_price if exit_price else current_price
return False
return False, None
def atr_based_trailing_stop(symbol, entry_price, current_price, initial_stop, position_type):
debug_print(f"Checking trailing stop: entry=${entry_price:.2f}, current=${current_price:.2f}")
@@ -1181,10 +1183,51 @@ def main():
debug_print(f"Max hold time exceeded, closing position")
qty = current_position_qty(SYMBOL)
if qty != 0:
exit_time = datetime.now(EASTERN)
hold_minutes = time_in_trade / 60
if position_type == 'long':
submit_market_sell(SYMBOL, qty)
exit_price = submit_market_sell(SYMBOL, qty)
pnl_dollars = (exit_price - entry_price) * qty if exit_price else 0
else:
submit_buy_to_cover(SYMBOL, abs(qty))
exit_price = submit_buy_to_cover(SYMBOL, abs(qty))
pnl_dollars = (entry_price - exit_price) * abs(qty) if exit_price else 0
pnl_percent = (pnl_dollars / (entry_price * abs(qty)) * 100) if entry_price > 0 and qty != 0 else 0
if pnl_dollars > 0:
winners += 1
elif pnl_dollars < 0:
losers += 1
risk_pct = abs((entry_price - stop_loss) / entry_price) if entry_price > 0 else 0
target_1 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_1 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_1
target_2 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_2 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_2
log_trade(
entry_time,
exit_time,
SYMBOL,
position_type,
entry_price,
exit_price if exit_price else current_price,
abs(qty),
entry_price * abs(qty),
stop_loss,
target_1,
target_2,
pnl_dollars,
pnl_percent,
hold_minutes,
'max_hold_time',
entry_regime,
entry_strength,
entry_rsi,
entry_adx,
entry_ma_spread,
0
)
position_active = False
trade_count += 1
position_state.reset()
@@ -1192,9 +1235,59 @@ def main():
time.sleep(POLL_INTERVAL)
continue
if scale_out_profit_taking(SYMBOL, entry_price, current_price, stop_loss, position_type):
target_hit, exit_price_target = scale_out_profit_taking(SYMBOL, entry_price, current_price, stop_loss, position_type)
if target_hit:
remaining_qty = current_position_qty(SYMBOL)
if remaining_qty == 0:
exit_time = datetime.now(EASTERN)
hold_minutes = (exit_time - entry_time).total_seconds() / 60 if entry_time else 0
if position_type == 'long':
pnl_dollars = (exit_price_target - entry_price) * abs(qty) if exit_price_target and qty != 0 else 0
else:
pnl_dollars = (entry_price - exit_price_target) * abs(qty) if exit_price_target and qty != 0 else 0
pnl_percent = (pnl_dollars / (entry_price * abs(qty)) * 100) if entry_price > 0 and qty != 0 else 0
if pnl_dollars > 0:
winners += 1
elif pnl_dollars < 0:
losers += 1
risk_pct = abs((entry_price - stop_loss) / entry_price) if entry_price > 0 else 0
target_1 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_1 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_1
target_2 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_2 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_2
try:
existing_position = api.get_position(SYMBOL)
original_qty = float(existing_position.qty)
except:
original_qty = qty
log_trade(
entry_time,
exit_time,
SYMBOL,
position_type,
entry_price,
exit_price_target if exit_price_target else current_price,
abs(original_qty),
entry_price * abs(original_qty),
stop_loss,
target_1,
target_2,
pnl_dollars,
pnl_percent,
hold_minutes,
'target_2_hit',
entry_regime,
entry_strength,
entry_rsi,
entry_adx,
entry_ma_spread,
0
)
position_active = False
position_state.reset()
debug_print(f"Sleeping {seconds_to_human_readable(POLL_INTERVAL)} after exit")
@@ -1258,12 +1351,6 @@ def main():
time.sleep(POLL_INTERVAL)
continue
if trades_today >= MAX_TRADES_PER_DAY:
logger.info(f"📊 Daily limit ({MAX_TRADES_PER_DAY}) - monitoring only")
debug_print(f"Daily trade limit reached ({trades_today}/{MAX_TRADES_PER_DAY})")
time.sleep(POLL_INTERVAL)
continue
signal, strength, signal_stop_loss, signal_position_type = advanced_signal_generator(SYMBOL)
bars_for_signal = get_recent_bars(SYMBOL, 50)
@@ -1284,6 +1371,14 @@ def main():
long_ma = sma(closes, LONG_WINDOW).iloc[-1]
signal_ma_spread = short_ma - long_ma
if trades_today >= MAX_TRADES_PER_DAY:
if signal in ['buy', 'sell'] and strength > 0:
log_missed_signal(datetime.now(EASTERN), signal, 'max_trades_per_day', current_price, SYMBOL, strength, signal_rsi, signal_adx, regime)
logger.info(f"📊 Daily limit ({MAX_TRADES_PER_DAY}) - monitoring only")
debug_print(f"Daily trade limit reached ({trades_today}/{MAX_TRADES_PER_DAY})")
time.sleep(POLL_INTERVAL)
continue
if signal == 'sell' and not ENABLE_SHORT_SELLING:
debug_print("Short selling disabled, ignoring sell signal")
if signal and strength > 0:
@@ -1427,6 +1522,56 @@ def main():
logger.info("🔚 Session ending...")
debug_print("Session ending, closing all positions...")
if position_active and entry_time:
exit_time = datetime.now(EASTERN)
hold_minutes = (exit_time - entry_time).total_seconds() / 60
qty = current_position_qty(SYMBOL)
if qty != 0:
bars_eod = get_recent_bars(SYMBOL, 10)
exit_price = bars_eod['close'].iloc[-1] if bars_eod is not None and len(bars_eod) > 0 else current_price
if position_type == 'long':
pnl_dollars = (exit_price - entry_price) * qty
else:
pnl_dollars = (entry_price - exit_price) * abs(qty)
pnl_percent = (pnl_dollars / (entry_price * abs(qty)) * 100) if entry_price > 0 and qty != 0 else 0
if pnl_dollars > 0:
winners += 1
elif pnl_dollars < 0:
losers += 1
risk_pct = abs((entry_price - stop_loss) / entry_price) if entry_price > 0 else 0
target_1 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_1 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_1
target_2 = entry_price + (entry_price - stop_loss) * PROFIT_TARGET_2 if position_type == 'long' else entry_price - (stop_loss - entry_price) * PROFIT_TARGET_2
log_trade(
entry_time,
exit_time,
SYMBOL,
position_type,
entry_price,
exit_price,
abs(qty),
entry_price * abs(qty),
stop_loss,
target_1,
target_2,
pnl_dollars,
pnl_percent,
hold_minutes,
'eod_close',
entry_regime,
entry_strength,
entry_rsi,
entry_adx,
entry_ma_spread,
0
)
close_all_positions()
final_equity = fetch_equity()