feat: robust fee collection in clp_manager.py - positions in 'CLOSING' state are now monitored and fee collection retries until successful before marking as 'CLOSED'

This commit is contained in:
2026-01-02 11:52:41 +01:00
parent 138e98fc49
commit c29dc2c8ac

View File

@ -739,12 +739,14 @@ def main():
while True: while True:
try: try:
status_data = load_status_data() status_data = load_status_data()
open_positions = [p for p in status_data if p.get('status') == 'OPEN'] # Include CLOSING status to ensure we finish what we started (fee collection retries)
open_positions = [p for p in status_data if p.get('status') in ['OPEN', 'CLOSING']]
active_auto_pos = next((p for p in open_positions if p.get('type') == 'AUTOMATIC'), None) active_auto_pos = next((p for p in open_positions if p.get('type') == 'AUTOMATIC'), None)
if active_auto_pos: if active_auto_pos:
token_id = active_auto_pos['token_id'] token_id = active_auto_pos['token_id']
current_status = active_auto_pos.get('status')
pos_details, pool_c = get_position_details(w3, npm, factory, token_id) pos_details, pool_c = get_position_details(w3, npm, factory, token_id)
if pos_details: if pos_details:
@ -851,29 +853,33 @@ def main():
'hedge_pnl_realized_usd': active_auto_pos.get('hedge_pnl_realized', 0.0), 'hedge_pnl_realized_usd': active_auto_pos.get('hedge_pnl_realized', 0.0),
'hedge_fees_paid_usd': active_auto_pos.get('hedge_fees_paid', 0.0) 'hedge_fees_paid_usd': active_auto_pos.get('hedge_fees_paid', 0.0)
} }
# We use 'target_value' as a proxy for 'Initial Hedge Equity' + 'Initial Uni Val' if strictly tracking strategy?
# For now, let's pass what we have.
# To get 'hedge_equity', we ideally need clp_hedger to write it to JSON.
# Current implementation of kpi_tracker uses 'hedge_equity' in NAV.
# If we leave it 0, NAV will be underreported.
# WORKAROUND: Assume Hedge PnL Realized IS the equity change if we ignore margin.
log_kpi_snapshot(snapshot) log_kpi_snapshot(snapshot)
if not in_range and CLOSE_POSITION_ENABLED: # --- CLOSING LOGIC ---
logger.warning(f"🛑 Closing Position {token_id} (Out of Range)") if current_status == "CLOSING" or (not in_range and CLOSE_POSITION_ENABLED):
update_position_status(token_id, "CLOSING") if current_status != "CLOSING":
logger.warning(f"🛑 Closing Position {token_id} (Out of Range)")
update_position_status(token_id, "CLOSING")
# 1. Remove Liquidity # 1. Remove Liquidity (if any left)
if decrease_liquidity(w3, npm, account, token_id, pos_details['liquidity'], pos_details['token0_decimals'], pos_details['token1_decimals']): liq_to_remove = pos_details['liquidity']
# 2. Collect Fees success_liq = True
collect_fees(w3, npm, account, token_id) if liq_to_remove > 0:
update_position_status(token_id, "CLOSED") success_liq = decrease_liquidity(w3, npm, account, token_id, liq_to_remove, pos_details['token0_decimals'], pos_details['token1_decimals'])
# 3. Optional Rebalance (Sell 50% WETH if fell below) # 2. Collect Fees (Retry if previous attempt failed or if liquidity was just removed)
if REBALANCE_ON_CLOSE_BELOW_RANGE and current_tick < tick_lower: if success_liq:
# Simple rebalance logic here (similar to original check_and_swap surplus logic) if collect_fees(w3, npm, account, token_id):
pass update_position_status(token_id, "CLOSED")
# 3. Optional Rebalance (Sell 50% WETH if fell below)
if REBALANCE_ON_CLOSE_BELOW_RANGE and current_tick < tick_lower:
# Simple rebalance logic here (similar to original check_and_swap surplus logic)
pass
else:
logger.error(f"❌ Fee collection failed for {token_id}. Will retry in next loop.")
else:
logger.error(f"❌ Liquidity removal failed for {token_id}. Will retry in next loop.")
elif OPEN_POSITION_ENABLED: elif OPEN_POSITION_ENABLED:
logger.info("🔍 No active position. Analyzing market (Fast scan: 37s)...") logger.info("🔍 No active position. Analyzing market (Fast scan: 37s)...")