-
Notifications
You must be signed in to change notification settings - Fork 0
PR #568: Add /admin/walkforward endpoint #437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1274,6 +1274,40 @@ | |||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| @app.get("/admin/walkforward") | ||||||||||||
| @app.post("/admin/walkforward") | ||||||||||||
| async def admin_walkforward(folds: int = 3): | ||||||||||||
| """Run walk-forward backtest export + fold analysis. | ||||||||||||
| Exports graded legs from bet_ledger, runs propiq_walkforward_backtest.py, | ||||||||||||
| saves results to data/walkforward_results.json. | ||||||||||||
| Usage: POST /admin/walkforward or GET /admin/walkforward?folds=5 | ||||||||||||
| """ | ||||||||||||
| async def _run_walkforward(): | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This background task lacks concurrency control. Multiple requests to this endpoint will trigger multiple backtests simultaneously, potentially leading to resource exhaustion or file write conflicts in the output directory. Consider implementing a guard (e.g., a global boolean flag or an 'asyncio.Lock') to prevent concurrent executions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Micro-Learning Topic: Resource exhaustion (Detected by phrase)Matched on "resource exhaustion"Allocating objects or timers with user-controlled sizes or durations can cause resource exhaustion. Try a challenge in Secure Code Warrior |
||||||||||||
| try: | ||||||||||||
|
Comment on lines
+1287
to
+1288
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 'importlib' module is not defined in this scope, which will cause a 'NameError' when calling 'importlib.util.find_spec'. Additionally, 'importlib.util' must be explicitly imported to access the 'util' submodule and the base 'importlib' package.
Suggested change
|
||||||||||||
| loop = asyncio.get_event_loop() | ||||||||||||
| spec_wf = importlib.util.find_spec("wire_walkforward_backtest") | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||
| spec_bt = importlib.util.find_spec("propiq_walkforward_backtest") | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||
| if spec_wf is None or spec_bt is None: | ||||||||||||
| logger.warning("[walkforward] Required scripts not found — skipping") | ||||||||||||
| return | ||||||||||||
| wf_mod = importlib.import_module("wire_walkforward_backtest") | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||
| bt_mod = importlib.import_module("propiq_walkforward_backtest") | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||
| await loop.run_in_executor(None, wf_mod.export_from_db) | ||||||||||||
| await loop.run_in_executor(None, bt_mod.run, folds) | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 'propiq_walkforward_backtest' module does not contain a 'run' function. Calling 'bt_mod.run(folds)' will raise an 'AttributeError'. Based on the module's content, you likely intended to call 'run_walkforward_backtest', but that function requires 'pitching_df' and 'prop_lines_df' DataFrames as input. Ensure the intended function is defined or use a wrapper that handles data loading. |
||||||||||||
| logger.info("[walkforward] Walk-forward backtest complete (%d folds).", folds) | ||||||||||||
| except Exception as exc: | ||||||||||||
| logger.error("[walkforward] Failed: %s", exc, exc_info=True) | ||||||||||||
|
|
||||||||||||
| asyncio.create_task(_run_walkforward()) | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Prevent concurrent Prompt for AI agents |
||||||||||||
| return JSONResponse({ | ||||||||||||
| "status": "started", | ||||||||||||
| "message": f"Walk-forward backtest running in background (~3-5 min, {folds} folds). " | ||||||||||||
| "Results written to data/walkforward_results.json when complete.", | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a discrepancy between the response message and the actual script output. The message points to 'data/walkforward_results.json', but 'propiq_walkforward_backtest.py' is configured to write its summary to 'backtest_results/walkforward_summary.json' (line 699).
Suggested change
|
||||||||||||
| }) | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| @app.get("/admin/scan-logs") | ||||||||||||
| async def admin_scan_logs(hours: int = 6): | ||||||||||||
| """ | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'folds' parameter should be validated to ensure it is a positive integer. If 'folds=0' is passed, it will cause a 'ZeroDivisionError' in 'propiq_walkforward_backtest.py' at line 562 during the fold size calculation.