Let me first understand the current codebase state after the revert to v25:
Now I have full context. Let me also read the HTML section where the pnl-summary and copy-trades panel is rendered:
Now let me also read the remaining part of app.py (the stream endpoint and positions API):
Now I have full context of the entire codebase. Let me create a plan for all 4 features the user wants:
Let me start with Task 1. The fetcher already captures side (BUY/SELL). I need to enhance it to detect position direction (OPEN LONG vs CLOSE LONG) and store that info. Let me implement all features together since they're interconnected:
Task 1: Detect BUY/SELL direction in fetcher.py
Now add the direction column to the DB schema and the end_date column to copy_trades:
Now let me update the DB schema to add direction column to trades and end_date column to copy_trades, plus add the migration entries:
Now add migration entries for the new columns:
Now let me move to Task 2 and 3 - add get_market_end_date(), a resolution checker, and update the copy trading loop to store end_date. Let me add these after the stop_copy_engine function:
Now start the resolution checker thread when the engine starts:
Now update the copy trading loop to store end_date when inserting copy trades. Let me find the INSERT INTO copy_trades line:
Now let me move to tasks 2 and 4 - update the HTML template to show event timers, direction badges, and a proper closed positions section. Let me update the renderCopyTrades function and add the timer:
Now I need to update the HTML template to add the timer, direction badges, and closed positions display. Let me re-read the full current renderCopyTrades area:
Now I'll add CSS for the timer and direction badges, then update the renderCopyTrades function:
Now update the renderCopyTrades function to include timer, direction, and improve the display:
Now let me add a "Closed Positions" section below the Copy Trade History card. Let me re-read the relevant HTML area:
Now I need to add the renderClosedPositions function in the JavaScript. Let me add it after the fetchPnlSummary function:
Let me find the fetchPnlSummary function:
Now add the renderClosedPositions function after fetchPnlSummary:
Now update the fetchCopyTrades function to also call renderClosedPositions:
Now let me also update the Trade Feed to show the direction column. Let me update the renderTrades function:
Now mark all tasks done:
Here's a summary of all changes made across fetcher.py, app.py, and index.html:
detect_trade_direction() that analyzes existing positions to label each trade as OPEN (new long), CLOSE (fully exiting), or REDUCE (partially selling). This is stored in a new direction column on the trades table and shown as colored badges (green OPEN / red CLOSE / yellow REDUCE) in both the Trade Feed and Copy Trade History.get_market_end_date() which fetches the end date from the Gamma API for each market. New copy trades store this in an end_date column. The UI shows a live countdown timer in the "Ends In" column, color-coded by urgency (cyan > yellow > orange > red). A backfill_end_dates() function populates end dates for existing trades on engine startup.resolution_checker_loop() that runs every 30 seconds in a background thread, querying the Gamma API for resolved markets. When a market resolves, it automatically determines the winning outcome, calculates PnL, and closes all matching open copy trades with WIN/LOSS results.The "database is locked" error is a SQLite concurrency problem - multiple threads (fetcher, copy engine, resolution checker) are all hitting the DB at the same time. Let me fix this properly.
I see the problem. Both app.py and fetcher.py create plain sqlite3.connect() calls without any timeout or WAL mode, and multiple threads compete for writes. I need to:
timeout to all connections so they wait instead of failingcheck_same_thread=False where neededNow fix both files:
Now fix the log_event function in fetcher.py which also creates its own raw connection:
You can send messages while the preview loads