From 7001309fd09ae9df27272d366fbe63965e8fa1c1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 23 Sep 2026 18:10:47 +0200 Subject: [PATCH] fix(freqai): bound continuation and correct RL accounting --- README.md | 22 +- ReforceXY/.basedpyright/diagnostics.json | 492 +++++++++--------- ReforceXY/reward_space_analysis/README.md | 9 +- .../reward_space_analysis.py | 9 +- .../tests/pbrs/test_pbrs.py | 61 ++- ReforceXY/tests/test_portfolio_returns.py | 76 ++- ReforceXY/tests/test_review_contracts.py | 7 +- ReforceXY/tests/test_training_observations.py | 84 +++ ReforceXY/user_data/freqaimodels/ReforceXY.py | 31 +- quickadapter/.basedpyright/diagnostics.json | 200 +++---- .../freqaimodels/QuickAdapterRegressorV3.py | 23 +- 11 files changed, 598 insertions(+), 416 deletions(-) diff --git a/README.md b/README.md index 35d248f..77fb5da 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,12 @@ below. | freqai.optuna_hyperopt.reset_label_study_on_schema_mismatch | true | bool | Reset a persisted `label` study when its selection schema is missing, invalid, or incompatible. `true` performs a destructive reset, deleting the study before recreating it; `false` preserves its trials and stored metadata, permits caller-managed reuse in memory, and does not persist selected params until the schema is reconciled. Both fail closed: an inspection error, or (under `true`) a deletion error, aborts study creation. Has no effect when `continuous=true` or outside live/dry-run modes, where studies are always reset. | | freqai.optuna_hyperopt.vary_model_seed_by_trial | true | bool | Add `trial.number` to each regressor's configured model seed (or its default seed of `1`) during HPO. `true` samples model randomness across trials; `false` evaluates every trial and the final fit with the same model seed. This does not change `freqai.optuna_hyperopt.seed`. | +In backtests, continual training uses only a saved model whose training cutoff +precedes the current window's end and its last available candle boundary. A +later model left under the same identifier is not reused when a backtest is +extended into the past. Live and dry-run restarts still restore compatible +deployed models. + The `label_weighting`, `label_smoothing`, `label_pipeline` and `label_prediction` sections accept either the flat paths listed above or a per-label format using `default` and `columns.`. Do not mix both formats in @@ -369,6 +375,12 @@ deployments without the chronological training marker. Training disables `shuffle_after_split`. HPO studies and saved best parameters are reused only when their objective identity matches. +Backtests continue only from a saved policy whose training cutoff precedes +the current window's end and its last available candle boundary. A later +deployment under the same identifier is not reused for an earlier window, +even when FreqAI has saved only metadata for intervening windows. Live and +dry-run restarts still restore compatible deployed policies. + ### Live inference Optional `fit_live_predictions_candles` statistics use the latest persisted real @@ -430,10 +442,12 @@ delta over the returned next observation. Termination liquidates any remaining position once and clears the terminal potential. `get_env_history()` returns one metrics/price row per transition. Its `execution_tick` is the transition/action/fill key before the tick increment; its `tick` is the returned post-increment price and -observation row (normally `execution_tick + 1`). Ordered trade events remain -separate in `trade_history`, where each event's `tick` equals the history row's -`execution_tick`; multiple events may share that key. `terminal_liquidation` and -`exit_pnl` remain on the transition history row. +observation row (normally `execution_tick + 1`). Exit-efficiency extrema include +the fee-adjusted PnL at entry and subsequent retained market marks. Ordered +trade events remain separate in `trade_history`: their tick identifies the +candle whose price filled the event. Action fills use `execution_tick`; +terminal liquidations use the returned post-increment tick. `terminal_liquidation` +and `exit_pnl` remain on the transition history row. ## Development diff --git a/ReforceXY/.basedpyright/diagnostics.json b/ReforceXY/.basedpyright/diagnostics.json index a305e4b..c81cc3a 100644 --- a/ReforceXY/.basedpyright/diagnostics.json +++ b/ReforceXY/.basedpyright/diagnostics.json @@ -33,343 +33,343 @@ }, { "endCharacter": 5, - "endLine": 2095, + "endLine": 2096, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"cut\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 17, - "startLine": 2090 + "startLine": 2091 }, { "endCharacter": 21, - "endLine": 2092, + "endLine": 2093, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"_Array1D[Any]\" cannot be assigned to parameter \"bins\" of type \"int | Sequence[float] | Index[int] | Index[float] | IntervalIndex[Interval[Any]] | Series[Any]\" in function \"cut\"\n  Type \"_Array1D[Any]\" is not assignable to type \"int | Sequence[float] | Index[int] | Index[float] | IntervalIndex[Interval[Any]] | Series[Any]\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"int\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"Sequence[float]\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"Index[int]\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"Index[float]\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"IntervalIndex[Interval[Any]]\"\n    \"ndarray[tuple[int], dtype[Any]]\" is not assignable to \"Series[Any]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 13, - "startLine": 2092 + "startLine": 2093 }, { "endCharacter": 5, - "endLine": 2117, + "endLine": 2118, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Type \"dict[bytes, bytes] | dict[str, RewardParamValue]\" is not assignable to declared type \"RewardParams\"\n  Type \"dict[bytes, bytes] | dict[str, RewardParamValue]\" is not assignable to type \"RewardParams\"\n    \"dict[bytes, bytes]\" is not assignable to \"dict[str, RewardParamValue]\"\n      Type parameter \"_KT@dict\" is invariant, but \"bytes\" is not the same as \"str\"\n      Type parameter \"_VT@dict\" is invariant, but \"bytes\" is not the same as \"RewardParamValue\"", "rule": "reportAssignmentType", "severity": "error", "startCharacter": 34, - "startLine": 2113 + "startLine": 2114 }, { "endCharacter": 43, - "endLine": 2114, + "endLine": 2115, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"__init__\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 8, - "startLine": 2114 + "startLine": 2115 }, { "endCharacter": 42, - "endLine": 2114, + "endLine": 2115, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"iterable\" of type \"Iterable[list[bytes]]\" in function \"__init__\"\n  Type \"Any | None\" is not assignable to type \"Iterable[list[bytes]]\"\n    \"None\" is incompatible with protocol \"Iterable[list[bytes]]\"\n      \"__iter__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 13, - "startLine": 2114 + "startLine": 2115 }, { "endCharacter": 60, - "endLine": 2374, + "endLine": 2375, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"importances_mean\" for class \"dict[Unknown, Bunch]\"\n  Attribute \"importances_mean\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 44, - "startLine": 2374 + "startLine": 2375 }, { "endCharacter": 58, - "endLine": 2375, + "endLine": 2376, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"importances_std\" for class \"dict[Unknown, Bunch]\"\n  Attribute \"importances_std\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 43, - "startLine": 2375 + "startLine": 2376 }, { "endCharacter": 88, - "endLine": 2394, + "endLine": 2395, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"columns\" for class \"NDArray[Unknown]\"\n  Attribute \"columns\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 81, - "startLine": 2394 + "startLine": 2395 }, { "endCharacter": 88, - "endLine": 2394, + "endLine": 2395, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"columns\" for class \"list[Unknown]\"\n  Attribute \"columns\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 81, - "startLine": 2394 + "startLine": 2395 }, { "endCharacter": 17, - "endLine": 2403, + "endLine": 2404, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Object of type \"None\" cannot be called", "rule": "reportOptionalCall", "severity": "error", "startCharacter": 28, - "startLine": 2397 + "startLine": 2398 }, { "endCharacter": 40, - "endLine": 2632, + "endLine": 2633, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | object | NAType | Unknown\" cannot be assigned to parameter \"arg1\" of type \"SupportsRichComparisonT@min\" in function \"min\"\n  Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n    Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n      Type \"object\" is not assignable to type \"SupportsRichComparison\"\n        \"object\" is incompatible with protocol \"SupportsDunderLT[Any]\"\n          \"__lt__\" is not present\n        \"object\" is incompatible with protocol \"SupportsDunderGT[Any]\"\n          \"__gt__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 22, - "startLine": 2632 + "startLine": 2633 }, { "endCharacter": 38, - "endLine": 2632, + "endLine": 2633, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"min\" for class \"ExtensionArray\"\n  Attribute \"min\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 35, - "startLine": 2632 + "startLine": 2633 }, { "endCharacter": 59, - "endLine": 2632, + "endLine": 2633, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | object | NAType | Unknown\" cannot be assigned to parameter \"arg2\" of type \"SupportsRichComparisonT@min\" in function \"min\"\n  Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n    Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n      Type \"object\" is not assignable to type \"SupportsRichComparison\"\n        \"object\" is incompatible with protocol \"SupportsDunderLT[Any]\"\n          \"__lt__\" is not present\n        \"object\" is incompatible with protocol \"SupportsDunderGT[Any]\"\n          \"__gt__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 42, - "startLine": 2632 + "startLine": 2633 }, { "endCharacter": 57, - "endLine": 2632, + "endLine": 2633, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"min\" for class \"ExtensionArray\"\n  Attribute \"min\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 54, - "startLine": 2632 + "startLine": 2633 }, { "endCharacter": 40, - "endLine": 2633, + "endLine": 2634, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | object | NAType | Unknown\" cannot be assigned to parameter \"arg1\" of type \"SupportsRichComparisonT@max\" in function \"max\"\n  Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n    Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n      Type \"object\" is not assignable to type \"SupportsRichComparison\"\n        \"object\" is incompatible with protocol \"SupportsDunderLT[Any]\"\n          \"__lt__\" is not present\n        \"object\" is incompatible with protocol \"SupportsDunderGT[Any]\"\n          \"__gt__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 22, - "startLine": 2633 + "startLine": 2634 }, { "endCharacter": 38, - "endLine": 2633, + "endLine": 2634, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"max\" for class \"ExtensionArray\"\n  Attribute \"max\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 35, - "startLine": 2633 + "startLine": 2634 }, { "endCharacter": 59, - "endLine": 2633, + "endLine": 2634, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | object | NAType | Unknown\" cannot be assigned to parameter \"arg2\" of type \"SupportsRichComparisonT@max\" in function \"max\"\n  Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n    Type \"Any | object | NAType | Unknown\" is not assignable to type \"SupportsRichComparison\"\n      Type \"object\" is not assignable to type \"SupportsRichComparison\"\n        \"object\" is incompatible with protocol \"SupportsDunderLT[Any]\"\n          \"__lt__\" is not present\n        \"object\" is incompatible with protocol \"SupportsDunderGT[Any]\"\n          \"__gt__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 42, - "startLine": 2633 + "startLine": 2634 }, { "endCharacter": 57, - "endLine": 2633, + "endLine": 2634, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"max\" for class \"ExtensionArray\"\n  Attribute \"max\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 54, - "startLine": 2633 + "startLine": 2634 }, { "endCharacter": 76, - "endLine": 2649, + "endLine": 2650, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"histogram\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 24, - "startLine": 2649 + "startLine": 2650 }, { "endCharacter": 49, - "endLine": 2649, + "endLine": 2650, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"a\" of type \"_ArrayLikeComplex_co\" in function \"histogram\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"_ArrayLikeComplex_co\"\n    Type \"ExtensionArray\" is not assignable to type \"_ArrayLikeComplex_co\"\n      \"ExtensionArray\" is incompatible with protocol \"_SupportsArray[dtype[numpy.bool[builtins.bool] | number[Any, Any]]]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[numpy.bool[builtins.bool] | number[Any, Any]]]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 37, - "startLine": 2649 + "startLine": 2650 }, { "endCharacter": 74, - "endLine": 2650, + "endLine": 2651, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"histogram\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 23, - "startLine": 2650 + "startLine": 2651 }, { "endCharacter": 47, - "endLine": 2650, + "endLine": 2651, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"a\" of type \"_ArrayLikeComplex_co\" in function \"histogram\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"_ArrayLikeComplex_co\"\n    Type \"ExtensionArray\" is not assignable to type \"_ArrayLikeComplex_co\"\n      \"ExtensionArray\" is incompatible with protocol \"_SupportsArray[dtype[numpy.bool[builtins.bool] | number[Any, Any]]]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[numpy.bool[builtins.bool] | number[Any, Any]]]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 36, - "startLine": 2650 + "startLine": 2651 }, { "endCharacter": 51, - "endLine": 2678, + "endLine": 2679, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"u_values\" of type \"ToFloatND\" in function \"wasserstein_distance\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"ToFloatND\"\n    Type \"ExtensionArray\" is not assignable to type \"ToFloatND\"\n      \"ExtensionArray\" is incompatible with protocol \"_CanArrayND[floating_co]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"SequenceND[py_float | _CanArray[floating_co]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 39, - "startLine": 2678 + "startLine": 2679 }, { "endCharacter": 64, - "endLine": 2678, + "endLine": 2679, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"v_values\" of type \"ToFloatND\" in function \"wasserstein_distance\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"ToFloatND\"\n    Type \"ExtensionArray\" is not assignable to type \"ToFloatND\"\n      \"ExtensionArray\" is incompatible with protocol \"_CanArrayND[floating_co]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"SequenceND[py_float | _CanArray[floating_co]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 53, - "startLine": 2678 + "startLine": 2679 }, { "endCharacter": 68, - "endLine": 2681, + "endLine": 2682, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"ks_2samp\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 27, - "startLine": 2681 + "startLine": 2682 }, { "endCharacter": 54, - "endLine": 2681, + "endLine": 2682, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"data1\" of type \"ToFloatND\" in function \"ks_2samp\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"ToFloatND\"\n    Type \"ExtensionArray\" is not assignable to type \"ToFloatND\"\n      \"ExtensionArray\" is incompatible with protocol \"_CanArrayND[floating_co]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"SequenceND[py_float | _CanArray[floating_co]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 42, - "startLine": 2681 + "startLine": 2682 }, { "endCharacter": 67, - "endLine": 2681, + "endLine": 2682, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"data2\" of type \"ToFloatND\" in function \"ks_2samp\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"ToFloatND\"\n    Type \"ExtensionArray\" is not assignable to type \"ToFloatND\"\n      \"ExtensionArray\" is incompatible with protocol \"_CanArrayND[floating_co]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"SequenceND[py_float | _CanArray[floating_co]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 56, - "startLine": 2681 + "startLine": 2682 }, { "endCharacter": 29, - "endLine": 2981, + "endLine": 2982, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"ptp\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 11, - "startLine": 2981 + "startLine": 2982 }, { "endCharacter": 28, - "endLine": 2981, + "endLine": 2982, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" cannot be assigned to parameter \"a\" of type \"_ArrayLikeNumeric_co\" in function \"ptp\"\n  Type \"np_1darray[Any] | ExtensionArray | Categorical[object]\" is not assignable to type \"_ArrayLikeNumeric_co\"\n    Type \"ExtensionArray\" is not assignable to type \"_ArrayLikeNumeric_co\"\n      \"ExtensionArray\" is incompatible with protocol \"_SupportsArray[dtype[number[Any, Any] | numpy.bool[builtins.bool] | object_ | timedelta64[Any]]]\"\n        \"__array__\" is not present\n      \"ExtensionArray\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[number[Any, Any] | numpy.bool[builtins.bool] | object_ | timedelta64[Any]]]]\"\n        \"__reversed__\" is not present\n        \"count\" is not present\n        \"index\" is not present\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 18, - "startLine": 2981 + "startLine": 2982 }, { "endCharacter": 65, - "endLine": 2990, + "endLine": 2991, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"mean\" for class \"Categorical[object]\"\n  Attribute \"mean\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 61, - "startLine": 2990 + "startLine": 2991 }, { "endCharacter": 65, - "endLine": 2990, + "endLine": 2991, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Cannot access attribute \"mean\" for class \"ExtensionArray\"\n  Attribute \"mean\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 61, - "startLine": 2990 + "startLine": 2991 }, { "endCharacter": 5, - "endLine": 3886, + "endLine": 3887, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Type \"dict[bytes, bytes] | dict[str, RewardParamValue]\" is not assignable to declared type \"RewardParams\"\n  Type \"dict[bytes, bytes] | dict[str, RewardParamValue]\" is not assignable to type \"RewardParams\"\n    \"dict[bytes, bytes]\" is not assignable to \"dict[str, RewardParamValue]\"\n      Type parameter \"_KT@dict\" is invariant, but \"bytes\" is not the same as \"str\"\n      Type parameter \"_VT@dict\" is invariant, but \"bytes\" is not the same as \"RewardParamValue\"", "rule": "reportAssignmentType", "severity": "error", "startCharacter": 34, - "startLine": 3882 + "startLine": 3883 }, { "endCharacter": 43, - "endLine": 3883, + "endLine": 3884, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "No overloads for \"__init__\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 8, - "startLine": 3883 + "startLine": 3884 }, { "endCharacter": 42, - "endLine": 3883, + "endLine": 3884, "file": "ReforceXY/reward_space_analysis/reward_space_analysis.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"iterable\" of type \"Iterable[list[bytes]]\" in function \"__init__\"\n  Type \"Any | None\" is not assignable to type \"Iterable[list[bytes]]\"\n    \"None\" is incompatible with protocol \"Iterable[list[bytes]]\"\n      \"__iter__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 13, - "startLine": 3883 + "startLine": 3884 }, { "endCharacter": 22, @@ -403,893 +403,893 @@ }, { "endCharacter": 38, - "endLine": 1477, + "endLine": 1499, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"obj\" of type \"Sized\" in function \"len\"\n  Type \"Any | None\" is not assignable to type \"Sized\"\n    \"None\" is incompatible with protocol \"Sized\"\n      \"__len__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 30, - "startLine": 1477 + "startLine": 1499 }, { "endCharacter": 36, - "endLine": 1481, + "endLine": 1503, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"obj\" of type \"Sized\" in function \"len\"\n  Type \"Any | None\" is not assignable to type \"Sized\"\n    \"None\" is incompatible with protocol \"Sized\"\n      \"__len__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 29, - "startLine": 1481 + "startLine": 1503 }, { "endCharacter": 80, - "endLine": 1484, + "endLine": 1506, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"steps_to_days\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 52, - "startLine": 1484 + "startLine": 1506 }, { "endCharacter": 78, - "endLine": 1485, + "endLine": 1507, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"steps_to_days\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 50, - "startLine": 1485 + "startLine": 1507 }, { "endCharacter": 80, - "endLine": 1486, + "endLine": 1508, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"steps_to_days\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 52, - "startLine": 1486 + "startLine": 1508 }, { "endCharacter": 56, - "endLine": 1571, + "endLine": 1593, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"VecMonitor | SubprocVecEnv | Env[Unknown, Unknown]\" cannot be assigned to parameter \"eval_env\" of type \"VecEnv | None\" in function \"get_callbacks\"\n  Type \"VecMonitor | SubprocVecEnv | Env[Unknown, Unknown]\" is not assignable to type \"VecEnv | None\"\n    Type \"Env[Unknown, Unknown]\" is not assignable to type \"VecEnv | None\"\n      \"Env[Unknown, Unknown]\" is not assignable to \"VecEnv\"\n      \"Env[Unknown, Unknown]\" is not assignable to \"None\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 43, - "startLine": 1571 + "startLine": 1593 }, { "endCharacter": 84, - "endLine": 1591, + "endLine": 1613, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | list[float]\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | list[float]\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"list[float]\" is not assignable to type \"ConvertibleToFloat\"\n      \"list[float]\" is not assignable to \"str\"\n      \"list[float]\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 67, - "startLine": 1591 + "startLine": 1613 }, { "endCharacter": 84, - "endLine": 1591, + "endLine": 1613, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | list[float]\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | list[float]\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"list[float]\" is not assignable to type \"ConvertibleToFloat\"\n      \"list[float]\" is not assignable to \"str\"\n      \"list[float]\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 67, - "startLine": 1591 + "startLine": 1613 }, { "endCharacter": 44, - "endLine": 2665, + "endLine": 2687, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"best_trial_params\" is possibly unbound", "rule": "reportPossiblyUnboundVariable", "severity": "error", "startCharacter": 27, - "startLine": 2665 + "startLine": 2687 }, { "endCharacter": 12, - "endLine": 2685, + "endLine": 2707, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Parameter declaration \"seed\" is obscured by a declaration of the same name", "rule": "reportRedeclaration", "severity": "error", "startCharacter": 8, - "startLine": 2685 + "startLine": 2707 }, { "endCharacter": 16, - "endLine": 2686, + "endLine": 2708, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Parameter declaration \"env_info\" is obscured by a declaration of the same name", "rule": "reportRedeclaration", "severity": "error", "startCharacter": 8, - "startLine": 2686 + "startLine": 2708 }, { "endCharacter": 51, - "endLine": 2729, + "endLine": 2751, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"list[() -> BaseEnvironment]\" cannot be assigned to parameter \"env_fns\" of type \"list[() -> Env[Unknown, Unknown]]\" in function \"__init__\"\n  \"list[() -> BaseEnvironment]\" is not assignable to \"list[() -> Env[Unknown, Unknown]]\"\n    Type parameter \"_T@list\" is invariant, but \"() -> BaseEnvironment\" is not the same as \"() -> Env[Unknown, Unknown]\"\n    Consider switching from \"list\" to \"Sequence\" which is covariant", "rule": "reportArgumentType", "severity": "error", "startCharacter": 42, - "startLine": 2729 + "startLine": 2751 }, { "endCharacter": 53, - "endLine": 2735, + "endLine": 2757, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"list[() -> BaseEnvironment]\" cannot be assigned to parameter \"env_fns\" of type \"list[() -> Env[Unknown, Unknown]]\" in function \"__init__\"\n  \"list[() -> BaseEnvironment]\" is not assignable to \"list[() -> Env[Unknown, Unknown]]\"\n    Type parameter \"_T@list\" is invariant, but \"() -> BaseEnvironment\" is not the same as \"() -> Env[Unknown, Unknown]\"\n    Consider switching from \"list\" to \"Sequence\" which is covariant", "rule": "reportArgumentType", "severity": "error", "startCharacter": 45, - "startLine": 2735 + "startLine": 2757 }, { "endCharacter": 22, - "endLine": 2798, + "endLine": 2820, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for \"None\"", "rule": "reportOptionalOperand", "severity": "error", "startCharacter": 15, - "startLine": 2798 + "startLine": 2820 }, { "endCharacter": 96, - "endLine": 2800, + "endLine": 2822, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for \"None\"", "rule": "reportOptionalOperand", "severity": "error", "startCharacter": 89, - "startLine": 2800 + "startLine": 2822 }, { "endCharacter": 23, - "endLine": 2803, + "endLine": 2825, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for \"None\"", "rule": "reportOptionalOperand", "severity": "error", "startCharacter": 16, - "startLine": 2803 + "startLine": 2825 }, { "endCharacter": 98, - "endLine": 2805, + "endLine": 2827, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for \"None\"", "rule": "reportOptionalOperand", "severity": "error", "startCharacter": 91, - "startLine": 2805 + "startLine": 2827 }, { "endCharacter": 44, - "endLine": 2817, + "endLine": 2839, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for types \"Any | None\" and \"Any | int | None\"\n  Operator \"*\" not supported for types \"None\" and \"None\"\n  Operator \"*\" not supported for types \"None\" and \"int\"", "rule": "reportOperatorIssue", "severity": "error", "startCharacter": 15, - "startLine": 2817 + "startLine": 2839 }, { "endCharacter": 133, - "endLine": 2819, + "endLine": 2841, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \"*\" not supported for types \"Any | None\" and \"Any | int | None\"\n  Operator \"*\" not supported for types \"None\" and \"None\"\n  Operator \"*\" not supported for types \"None\" and \"int\"", "rule": "reportOperatorIssue", "severity": "error", "startCharacter": 106, - "startLine": 2819 + "startLine": 2841 }, { "endCharacter": 30, - "endLine": 2822, + "endLine": 2844, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Operator \">\" not supported for \"None\"", "rule": "reportOptionalOperand", "severity": "error", "startCharacter": 15, - "startLine": 2822 + "startLine": 2844 }, { "endCharacter": 54, - "endLine": 2887, + "endLine": 2909, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"is_pruned\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 45, - "startLine": 2887 + "startLine": 2909 }, { "endCharacter": 67, - "endLine": 2890, + "endLine": 2912, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"use_masking\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 56, - "startLine": 2890 + "startLine": 2912 }, { "endCharacter": 60, - "endLine": 2898, + "endLine": 2920, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"update_best_reward\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 42, - "startLine": 2898 + "startLine": 2920 }, { "endCharacter": 84, - "endLine": 2898, + "endLine": 2920, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | list[float]\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | list[float]\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"list[float]\" is not assignable to type \"ConvertibleToFloat\"\n      \"list[float]\" is not assignable to \"str\"\n      \"list[float]\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 67, - "startLine": 2898 + "startLine": 2920 }, { "endCharacter": 84, - "endLine": 2898, + "endLine": 2920, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | list[float]\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | list[float]\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"list[float]\" is not assignable to type \"ConvertibleToFloat\"\n      \"list[float]\" is not assignable to \"str\"\n      \"list[float]\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"list[float]\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 67, - "startLine": 2898 + "startLine": 2920 }, { "endCharacter": 46, - "endLine": 2952, + "endLine": 2974, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"is_pruned\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 37, - "startLine": 2952 + "startLine": 2974 }, { "endCharacter": 57, - "endLine": 2955, + "endLine": 2977, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"best_mean_reward\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 41, - "startLine": 2955 + "startLine": 2977 }, { "endCharacter": 37, - "endLine": 2965, + "endLine": 2987, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Cannot assign to attribute \"train_env\" for class \"ReforceXY*\"\n  Type \"None\" is not assignable to type \"VecMonitor | SubprocVecEnv | Env[Unknown, Unknown]\"\n    \"None\" is not assignable to \"VecMonitor\"\n    \"None\" is not assignable to \"SubprocVecEnv\"\n    \"None\" is not assignable to \"Env[Unknown, Unknown]\"", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 33, - "startLine": 2965 + "startLine": 2987 }, { "endCharacter": 36, - "endLine": 2970, + "endLine": 2992, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Cannot assign to attribute \"eval_env\" for class \"ReforceXY*\"\n  Type \"None\" is not assignable to type \"VecMonitor | SubprocVecEnv | Env[Unknown, Unknown]\"\n    \"None\" is not assignable to \"VecMonitor\"\n    \"None\" is not assignable to \"SubprocVecEnv\"\n    \"None\" is not assignable to \"Env[Unknown, Unknown]\"", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 32, - "startLine": 2970 + "startLine": 2992 }, { "endCharacter": 7, - "endLine": 3015, + "endLine": 3037, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Declaration \"MyRLEnv\" is obscured by a declaration of the same name", "rule": "reportRedeclaration", "severity": "error", "startCharacter": 0, - "startLine": 3015 + "startLine": 3037 }, { "endCharacter": 36, - "endLine": 3027, + "endLine": 3049, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Declaration \"_last_closed_trade_tick\" is obscured by a declaration of the same name", "rule": "reportRedeclaration", "severity": "error", "startCharacter": 13, - "startLine": 3027 + "startLine": 3049 }, { "endCharacter": 13, - "endLine": 3619, + "endLine": 3641, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Method \"reset\" overrides class \"BaseEnvironment\" in an incompatible manner\n  Return type mismatch: base method returns type \"tuple[DataFrame, dict[Unknown, Unknown]]\", override returns type \"tuple[NDArray[float32], dict[str, Any]]\"\n    \"tuple[NDArray[float32], dict[str, Any]]\" is not assignable to \"tuple[DataFrame, dict[Unknown, Unknown]]\"\n      Tuple entry 1 is incorrect type\n        \"ndarray[_AnyShape, dtype[float32]]\" is not assignable to \"DataFrame\"", "rule": "reportIncompatibleMethodOverride", "severity": "error", "startCharacter": 8, - "startLine": 3619 + "startLine": 3641 }, { "endCharacter": 26, - "endLine": 3640, + "endLine": 3662, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Type \"tuple[DataFrame, dict[Unknown, Unknown]]\" is not assignable to return type \"tuple[NDArray[float32], dict[str, Any]]\"\n  \"DataFrame\" is not assignable to \"ndarray[_AnyShape, dtype[float32]]\"", "rule": "reportReturnType", "severity": "error", "startCharacter": 15, - "startLine": 3640 + "startLine": 3662 }, { "endCharacter": 55, - "endLine": 3948, + "endLine": 3970, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 44, - "startLine": 3948 + "startLine": 3970 }, { "endCharacter": 55, - "endLine": 3948, + "endLine": 3970, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 44, - "startLine": 3948 + "startLine": 3970 }, { "endCharacter": 59, - "endLine": 3972, + "endLine": 3994, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 48, - "startLine": 3972 + "startLine": 3994 }, { "endCharacter": 59, - "endLine": 3972, + "endLine": 3994, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 48, - "startLine": 3972 + "startLine": 3994 }, { "endCharacter": 24, - "endLine": 4001, + "endLine": 4023, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Method \"_get_observation\" overrides class \"BaseEnvironment\" in an incompatible manner\n  Return type mismatch: base method returns type \"DataFrame\", override returns type \"NDArray[float32]\"\n    \"ndarray[_AnyShape, dtype[float32]]\" is not assignable to \"DataFrame\"", "rule": "reportIncompatibleMethodOverride", "severity": "error", "startCharacter": 8, - "startLine": 4001 + "startLine": 4023 }, { "endCharacter": 12, - "endLine": 4103, + "endLine": 4125, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Method \"step\" overrides class \"Base5ActionRLEnv\" in an incompatible manner\n  Return type mismatch: base method returns type \"tuple[DataFrame, float, bool, Literal[False], dict[str, Unknown]]\", override returns type \"tuple[NDArray[float32], float, bool, bool, dict[str, Any]]\"\n    \"tuple[NDArray[float32], float, bool, bool, dict[str, Any]]\" is not assignable to \"tuple[DataFrame, float, bool, Literal[False], dict[str, Unknown]]\"\n      Tuple entry 1 is incorrect type\n        \"ndarray[_AnyShape, dtype[float32]]\" is not assignable to \"DataFrame\"", "rule": "reportIncompatibleMethodOverride", "severity": "error", "startCharacter": 8, - "startLine": 4103 + "startLine": 4125 }, { "endCharacter": 20, - "endLine": 4290, + "endLine": 4315, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Method \"action_masks\" overrides class \"BaseEnvironment\" in an incompatible manner\n  Return type mismatch: base method returns type \"list[bool]\", override returns type \"NDArray[bool_]\"\n    \"ndarray[_AnyShape, dtype[bool_]]\" is not assignable to \"list[bool]\"", "rule": "reportIncompatibleMethodOverride", "severity": "error", "startCharacter": 8, - "startLine": 4290 + "startLine": 4315 }, { "endCharacter": 40, - "endLine": 4439, + "endLine": 4464, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "\"Figure\" is not exported from module \"matplotlib.pyplot\"", "rule": "reportPrivateImportUsage", "severity": "error", "startCharacter": 34, - "startLine": 4439 + "startLine": 4464 }, { "endCharacter": 54, - "endLine": 4942, + "endLine": 4967, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 45, - "startLine": 4942 + "startLine": 4967 }, { "endCharacter": 54, - "endLine": 4942, + "endLine": 4967, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 45, - "startLine": 4942 + "startLine": 4967 }, { "endCharacter": 50, - "endLine": 4954, + "endLine": 4979, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"object\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"object\" is not assignable to type \"ConvertibleToFloat\"\n    \"object\" is not assignable to \"str\"\n    \"object\" is incompatible with protocol \"Buffer\"\n      \"__buffer__\" is not present\n    \"object\" is incompatible with protocol \"SupportsFloat\"\n      \"__float__\" is not present\n    \"object\" is incompatible with protocol \"SupportsIndex\"\n      \"__index__\" is not present", "rule": "reportArgumentType", "severity": "error", "startCharacter": 37, - "startLine": 4954 + "startLine": 4979 }, { "endCharacter": 72, - "endLine": 4965, + "endLine": 4990, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 70, - "startLine": 4965 + "startLine": 4990 }, { "endCharacter": 72, - "endLine": 4965, + "endLine": 4990, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 70, - "startLine": 4965 + "startLine": 4990 }, { "endCharacter": 73, - "endLine": 4974, + "endLine": 4999, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 71, - "startLine": 4974 + "startLine": 4999 }, { "endCharacter": 73, - "endLine": 4974, + "endLine": 4999, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 71, - "startLine": 4974 + "startLine": 4999 }, { "endCharacter": 58, - "endLine": 4983, + "endLine": 5008, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 56, - "startLine": 4983 + "startLine": 5008 }, { "endCharacter": 58, - "endLine": 4983, + "endLine": 5008, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 56, - "startLine": 4983 + "startLine": 5008 }, { "endCharacter": 50, - "endLine": 5214, + "endLine": 5239, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Mapping[Unknown, Unknown]\" cannot be assigned to parameter \"src\" of type \"dict[str, Any]\" in function \"deepmerge\"\n  \"Mapping[Unknown, Unknown]\" is not assignable to \"dict[str, Any]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 49, - "startLine": 5214 + "startLine": 5239 }, { "endCharacter": 20, - "endLine": 5391, + "endLine": 5416, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 18, - "startLine": 5391 + "startLine": 5416 }, { "endCharacter": 20, - "endLine": 5391, + "endLine": 5416, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 18, - "startLine": 5391 + "startLine": 5416 }, { "endCharacter": 59, - "endLine": 5396, + "endLine": 5421, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5396 + "startLine": 5421 }, { "endCharacter": 59, - "endLine": 5396, + "endLine": 5421, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5396 + "startLine": 5421 }, { "endCharacter": 65, - "endLine": 5397, + "endLine": 5422, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5397 + "startLine": 5422 }, { "endCharacter": 65, - "endLine": 5397, + "endLine": 5422, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5397 + "startLine": 5422 }, { "endCharacter": 57, - "endLine": 5398, + "endLine": 5423, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5398 + "startLine": 5423 }, { "endCharacter": 57, - "endLine": 5398, + "endLine": 5423, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5398 + "startLine": 5423 }, { "endCharacter": 63, - "endLine": 5400, + "endLine": 5425, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5400 + "startLine": 5425 }, { "endCharacter": 63, - "endLine": 5400, + "endLine": 5425, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5400 + "startLine": 5425 }, { "endCharacter": 61, - "endLine": 5402, + "endLine": 5427, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 32, - "startLine": 5402 + "startLine": 5427 }, { "endCharacter": 61, - "endLine": 5402, + "endLine": 5427, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 32, - "startLine": 5402 + "startLine": 5427 }, { "endCharacter": 67, - "endLine": 5403, + "endLine": 5428, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 36, - "startLine": 5403 + "startLine": 5428 }, { "endCharacter": 67, - "endLine": 5403, + "endLine": 5428, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 36, - "startLine": 5403 + "startLine": 5428 }, { "endCharacter": 73, - "endLine": 5404, + "endLine": 5429, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 39, - "startLine": 5404 + "startLine": 5429 }, { "endCharacter": 73, - "endLine": 5404, + "endLine": 5429, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 39, - "startLine": 5404 + "startLine": 5429 }, { "endCharacter": 61, - "endLine": 5405, + "endLine": 5430, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 33, - "startLine": 5405 + "startLine": 5430 }, { "endCharacter": 61, - "endLine": 5405, + "endLine": 5430, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 33, - "startLine": 5405 + "startLine": 5430 }, { "endCharacter": 89, - "endLine": 5412, + "endLine": 5437, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 52, - "startLine": 5412 + "startLine": 5437 }, { "endCharacter": 89, - "endLine": 5412, + "endLine": 5437, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 52, - "startLine": 5412 + "startLine": 5437 }, { "endCharacter": 83, - "endLine": 5413, + "endLine": 5438, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 49, - "startLine": 5413 + "startLine": 5438 }, { "endCharacter": 83, - "endLine": 5413, + "endLine": 5438, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 49, - "startLine": 5413 + "startLine": 5438 }, { "endCharacter": 57, - "endLine": 5438, + "endLine": 5463, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5438 + "startLine": 5463 }, { "endCharacter": 57, - "endLine": 5438, + "endLine": 5463, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 31, - "startLine": 5438 + "startLine": 5463 }, { "endCharacter": 65, - "endLine": 5439, + "endLine": 5464, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5439 + "startLine": 5464 }, { "endCharacter": 65, - "endLine": 5439, + "endLine": 5464, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 34, - "startLine": 5439 + "startLine": 5464 }, { "endCharacter": 67, - "endLine": 5441, + "endLine": 5466, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 35, - "startLine": 5441 + "startLine": 5466 }, { "endCharacter": 67, - "endLine": 5441, + "endLine": 5466, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 35, - "startLine": 5441 + "startLine": 5466 }, { "endCharacter": 87, - "endLine": 5444, + "endLine": 5469, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 46, - "startLine": 5444 + "startLine": 5469 }, { "endCharacter": 87, - "endLine": 5444, + "endLine": 5469, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 46, - "startLine": 5444 + "startLine": 5469 }, { "endCharacter": 93, - "endLine": 5445, + "endLine": 5470, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 49, - "startLine": 5445 + "startLine": 5470 }, { "endCharacter": 93, - "endLine": 5445, + "endLine": 5470, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 49, - "startLine": 5445 + "startLine": 5470 }, { "endCharacter": 89, - "endLine": 5446, + "endLine": 5471, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 47, - "startLine": 5446 + "startLine": 5471 }, { "endCharacter": 89, - "endLine": 5446, + "endLine": 5471, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 47, - "startLine": 5446 + "startLine": 5471 }, { "endCharacter": 89, - "endLine": 5447, + "endLine": 5472, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 46, - "startLine": 5447 + "startLine": 5472 }, { "endCharacter": 89, - "endLine": 5447, + "endLine": 5472, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 46, - "startLine": 5447 + "startLine": 5472 }, { "endCharacter": 75, - "endLine": 5448, + "endLine": 5473, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 39, - "startLine": 5448 + "startLine": 5473 }, { "endCharacter": 75, - "endLine": 5448, + "endLine": 5473, "file": "ReforceXY/user_data/freqaimodels/ReforceXY.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n ...", "rule": "reportArgumentType", "severity": "error", "startCharacter": 39, - "startLine": 5448 + "startLine": 5473 }, { "endCharacter": 33, diff --git a/ReforceXY/reward_space_analysis/README.md b/ReforceXY/reward_space_analysis/README.md index 28ccd42..cbc1ac0 100644 --- a/ReforceXY/reward_space_analysis/README.md +++ b/ReforceXY/reward_space_analysis/README.md @@ -167,8 +167,8 @@ Generates shift metrics for comparison (see Outputs section). provided). - **`--unrealized_pnl`** (flag, default: false) – Transform the retained in-position synthetic price/PnL trajectory using fee-aware unrealized PnL. - This affects extrema and all enabled base, PBRS, and additive reward terms - that depend on PnL. (Simulation-only.) + This affects subsequent retained extrema and enabled reward terms that depend + on PnL. (Simulation-only.) ### Hybrid Simulation Scalars @@ -280,7 +280,6 @@ Let `pnl_target = profit_aim · risk_reward_ratio` and Let `max_u = max_unrealized_profit`, `min_u = min_unrealized_profit`, `range = max_u - min_u`, `ratio = (pnl - min_u)/range`, `min_range = max(1e-6, 0.01 · pnl_target)`. Then: - - If `range < min_range`: `efficiency_coefficient = 1` (guard against division explosion) - If `pnl > 0`: @@ -289,6 +288,10 @@ Let `max_u = max_unrealized_profit`, `min_u = min_unrealized_profit`, `efficiency_coefficient = 1 + efficiency_weight · (efficiency_center - ratio)` - Else: `efficiency_coefficient = 1` +The extrema start with the fee-adjusted PnL at the entry fill and then include +each retained market mark. In synthetic `unrealized_pnl` mode, a sampled +candidate discarded by the transform is not an extremum. + ##### Exit Attenuation | Parameter | Default | Description | diff --git a/ReforceXY/reward_space_analysis/reward_space_analysis.py b/ReforceXY/reward_space_analysis/reward_space_analysis.py index 960d072..f57d6e6 100644 --- a/ReforceXY/reward_space_analysis/reward_space_analysis.py +++ b/ReforceXY/reward_space_analysis/reward_space_analysis.py @@ -1767,15 +1767,16 @@ def simulate_samples( trade_duration = 0 idle_duration = 0 entry_open = current_open - max_unrealized_profit = -np.inf - min_unrealized_profit = np.inf elif action == Actions.Short_enter and short_allowed: position = Positions.Short trade_duration = 0 idle_duration = 0 entry_open = current_open - max_unrealized_profit = -np.inf - min_unrealized_profit = np.inf + if position in (Positions.Long, Positions.Short): + entry_pnl = _compute_unrealized_pnl_estimate( + position, entry_open=entry_open, current_open=entry_open, params=params + ) + max_unrealized_profit = min_unrealized_profit = entry_pnl else: idle_duration = 0 if action in (Actions.Long_exit, Actions.Short_exit): diff --git a/ReforceXY/reward_space_analysis/tests/pbrs/test_pbrs.py b/ReforceXY/reward_space_analysis/tests/pbrs/test_pbrs.py index 183a306..18e57dc 100644 --- a/ReforceXY/reward_space_analysis/tests/pbrs/test_pbrs.py +++ b/ReforceXY/reward_space_analysis/tests/pbrs/test_pbrs.py @@ -169,32 +169,32 @@ class TestSimulationParity(RewardSpaceTestBase): expected_duration = 0 self.assertEqual(row.trade_duration, expected_duration) - def test_first_retained_pnl_is_only_exit_extremum(self): - """A first-candle exit excludes the fill-time PnL from its extrema.""" + def test_synthetic_exit_reward_includes_fee_adjusted_entry_pnl(self): params = self.base_params( unrealized_pnl=False, max_trade_duration_candles=100, - entry_fee_rate=0.0, - exit_fee_rate=0.0, + entry_fee_rate=0.0015, + exit_fee_rate=0.0015, + exit_attenuation_mode="linear", + exit_plateau=False, hold_potential_enabled=False, entry_additive_enabled=False, exit_additive_enabled=False, ) actions = [ (Actions.Long_enter, 1.0, 0.0, 0.0), + (Actions.Neutral, 0.0, 0.0, 1.0), (Actions.Long_exit, 0.0, 1.0, 0.0), ] with ( patch.object(reward_space_analysis, "_sample_action", side_effect=actions), patch.object( - reward_space_analysis.random.Random, - "gauss", - side_effect=[0.02, 0.0], + reward_space_analysis.random.Random, "gauss", side_effect=[0.02, -0.01, 0.0] ), ): df = simulate_samples( params=params, - num_samples=2, + num_samples=3, seed=SEEDS.BASE, base_factor=PARAMS.BASE_FACTOR, profit_aim=PARAMS.PROFIT_AIM, @@ -205,30 +205,26 @@ class TestSimulationParity(RewardSpaceTestBase): pnl_duration_vol_scale=PARAMS.PNL_DUR_VOL_SCALE, ) - exit_row = df.iloc[1] + entry_pnl = 1.0 / ((1.0 + params["entry_fee_rate"]) * (1.0 + params["exit_fee_rate"])) - 1.0 + peak_pnl = float(df.iloc[0]["next_pnl"]) + exit_row = df.iloc[-1] pnl = float(exit_row["pnl"]) + self.assertLess(entry_pnl, 0.0) + self.assertGreater(peak_pnl, pnl) self.assertGreater(pnl, 0.0) - runtime_context = reward_space_analysis.RewardContext( - current_pnl=pnl, - trade_duration=int(exit_row["trade_duration"]), - idle_duration=0, - max_unrealized_profit=pnl, - min_unrealized_profit=pnl, - position=Positions.Long, - action=Actions.Long_exit, + efficiency = 1.0 + params["efficiency_weight"] * ( + (pnl - entry_pnl) / (peak_pnl - entry_pnl) - params["efficiency_center"] + ) + duration_ratio = float(exit_row["trade_duration"]) / params["max_trade_duration_candles"] + expected = ( + pnl + * params["base_factor"] + / (1.0 + params["exit_linear_slope"] * duration_ratio) + * efficiency ) - expected_exit = reward_space_analysis.calculate_reward( - runtime_context, - params, - PARAMS.BASE_FACTOR, - PARAMS.PROFIT_AIM, - PARAMS.RISK_REWARD_RATIO, - short_allowed=True, - action_masking=True, - ).exit_component self.assertAlmostEqualFloat( float(exit_row["reward_exit"]), - expected_exit, + expected, tolerance=TOLERANCE.IDENTITY_RELAXED, rtol=TOLERANCE.RELATIVE, ) @@ -334,8 +330,8 @@ class TestSimulationParity(RewardSpaceTestBase): ) self.assertTrue(replay["next_pnl"].equals(df["next_pnl"])) - def test_unrealized_pnl_exit_rewards_use_only_retained_extrema(self): - """Exit rewards use extrema reconstructed from the retained PnL trajectory.""" + def test_unrealized_pnl_exit_rewards_include_fill_and_retained_extrema(self): + """The fee-adjusted fill and retained prices determine exit efficiency.""" params = self.base_params( unrealized_pnl=True, max_trade_duration_candles=100, @@ -378,8 +374,11 @@ class TestSimulationParity(RewardSpaceTestBase): Actions.Long_enter, Actions.Short_enter, ): - max_unrealized = -np.inf - min_unrealized = np.inf + fee_factor = (1.0 + params["entry_fee_rate"]) * (1.0 + params["exit_fee_rate"]) + entry_pnl = ( + 1.0 / fee_factor - 1.0 if action == Actions.Long_enter else 1.0 - fee_factor + ) + max_unrealized = min_unrealized = entry_pnl if position in (Positions.Long, Positions.Short) and action in ( Actions.Long_exit, diff --git a/ReforceXY/tests/test_portfolio_returns.py b/ReforceXY/tests/test_portfolio_returns.py index b545b73..1fc5f21 100644 --- a/ReforceXY/tests/test_portfolio_returns.py +++ b/ReforceXY/tests/test_portfolio_returns.py @@ -6,7 +6,7 @@ import unittest import numpy as np import pandas as pd -from ReforceXY.user_data.freqaimodels.ReforceXY import Actions, MyRLEnv +from ReforceXY.user_data.freqaimodels.ReforceXY import Actions, MyRLEnv, ReforceXY class PortfolioReturnsTest(unittest.TestCase): @@ -46,6 +46,46 @@ class PortfolioReturnsTest(unittest.TestCase): self.assertEqual(info["most_recent_profit"], 0.0) self.assertAlmostEqual(np.expm1(env.portfolio_log_returns.sum()), env._total_profit - 1) + def test_exit_reward_includes_fee_adjusted_entry_extremum(self): + for short, mark in ((False, 110.0), (True, 90.0)): + with self.subTest(short=short): + env = self.make_env([100.0, 100.0, mark, mark, mark]) + entry = Actions.Short_enter if short else Actions.Long_enter + exit_action = Actions.Short_exit if short else Actions.Long_exit + fee_factor = (1.0 + env.fee) ** 2 + entry_pnl = 1.0 - fee_factor if short else 1.0 / fee_factor - 1.0 + exit_pnl = ( + 1.0 - mark / 100.0 * fee_factor if short else mark / 100.0 / fee_factor - 1.0 + ) + + env.step(entry.value) + self.assertAlmostEqual(env.get_min_unrealized_profit(), entry_pnl) + self.assertAlmostEqual(env.get_max_unrealized_profit(), exit_pnl) + _, reward, _, _, _ = env.step(exit_action.value) + + duration = 1.0 / env.max_trade_duration_candles + if ReforceXY.DEFAULT_EXIT_PLATEAU: + duration = max(0.0, duration - ReforceXY.DEFAULT_EXIT_PLATEAU_GRACE) + attenuation = 1.0 / (1.0 + ReforceXY.DEFAULT_EXIT_LINEAR_SLOPE * duration) + target_coefficient = 1.0 + if exit_pnl > env._pnl_target: + target_coefficient += ReforceXY.DEFAULT_WIN_REWARD_FACTOR * math.tanh( + ReforceXY.DEFAULT_PNL_AMPLIFICATION_SENSITIVITY + * (exit_pnl / env._pnl_target - 1.0) + ) + efficiency = 1.0 + ReforceXY.DEFAULT_EFFICIENCY_WEIGHT * ( + 1.0 - ReforceXY.DEFAULT_EFFICIENCY_CENTER + ) + self.assertAlmostEqual( + reward, + exit_pnl + * ReforceXY.DEFAULT_BASE_FACTOR + * attenuation + * target_coefficient + * efficiency, + places=9, + ) + def test_transitions_match_equity_for_both_staking_modes_and_directions(self): prices = [100.0, 100.0, 110.0, 105.0, 115.0, 120.0, 118.0, 117.0, 117.0] for short in (False, True): @@ -138,7 +178,6 @@ class PortfolioReturnsTest(unittest.TestCase): env.trade_history[-1]["type"], "short_exit" if short else "long_exit", ) - self.assertEqual(env.trade_history[-1]["tick"], info["execution_tick"]) self.assertEqual(env.trade_history[-1]["price"], terminal_price) self.assertAlmostEqual(env.trade_history[-1]["profit"], expected_pnl) self.assertAlmostEqual( @@ -212,7 +251,7 @@ class PortfolioReturnsTest(unittest.TestCase): else: pd.testing.assert_frame_equal(history, baseline) - def test_terminal_entry_preserves_two_events_and_plot_markers(self): + def test_terminal_fill_events_and_plot_match_their_price_candles(self): env = self.make_env([100.0, 100.0, 90.0]) _, _, terminated, truncated, info = env.step(Actions.Long_enter.value) expected_pnl = 90.0 / 100.0 / (1.0 + env.fee) ** 2 - 1.0 @@ -225,26 +264,29 @@ class PortfolioReturnsTest(unittest.TestCase): self.assertEqual(history.iloc[0]["execution_tick"], info["execution_tick"]) self.assertEqual(history.iloc[0]["open"], 90.0) - self.assertEqual(len(env.trade_history), 2) - self.assertEqual( - [(event["tick"], event["type"]) for event in env.trade_history], - [(info["execution_tick"], "long_enter"), (info["execution_tick"], "long_exit")], - ) - self.assertEqual( - [event["price"] for event in env.trade_history], - [100.0, 90.0], - ) - self.assertEqual(env.trade_history[0]["profit"], 0.0) - self.assertAlmostEqual(env.trade_history[1]["profit"], expected_pnl) + events = env.trade_history + self.assertEqual([event["type"] for event in events], ["long_enter", "long_exit"]) + for event in events: + self.assertAlmostEqual(event["price"], env.prices.iloc[event["tick"]]["open"]) + self.assertEqual(events[0]["profit"], 0.0) + self.assertAlmostEqual(events[1]["profit"], expected_pnl) figure = env.get_env_plot() - marker_lines = [ + curve = figure.axes[0].lines[0] + markers = [ line for line in figure.axes[0].lines if line.get_linestyle() == "None" and len(line.get_xdata()) == 1 ] - self.assertEqual([line.get_marker() for line in marker_lines], ["^", "."]) - self.assertEqual([line.get_xdata()[0] for line in marker_lines], [1, 1]) + self.assertEqual([line.get_marker() for line in markers], ["^", "."]) + self.assertEqual( + [(line.get_xdata()[0], line.get_ydata()[0]) for line in markers], + [(event["tick"], event["price"]) for event in events], + ) + self.assertEqual( + (markers[-1].get_xdata()[0], markers[-1].get_ydata()[0]), + (curve.get_xdata()[-1], curve.get_ydata()[-1]), + ) def test_nonpositive_equity_is_not_reported_as_zero_return(self): env = self.make_env([100.0, 100.0, 100.0, 300.0, 300.0], fee=0.0) diff --git a/ReforceXY/tests/test_review_contracts.py b/ReforceXY/tests/test_review_contracts.py index 09c00b8..2dc7cdb 100644 --- a/ReforceXY/tests/test_review_contracts.py +++ b/ReforceXY/tests/test_review_contracts.py @@ -667,16 +667,11 @@ class ReviewContractsTest(unittest.TestCase): ) self.assertAlmostEqual(entry_reward, env._potential_gamma * expected_potential) - _, exit_reward, exit_done, exit_truncated, _ = env.step(2) + _, _, exit_done, exit_truncated, _ = env.step(2) self.assertFalse(exit_done) self.assertFalse(exit_truncated) self.assertEqual(env.trade_history[-1]["tick"], 3) self.assertEqual(env.trade_history[-1]["price"], 110.0) - pnl_coefficient = 1.0 + 2.0 * math.tanh(2.0 * (observed_pnl / env._pnl_target - 1.0)) - # The entry transition retains one PnL observation, so max equals min - # and the independent efficiency formula remains at its neutral value 1.0. - expected_base_exit = observed_pnl * ReforceXY.DEFAULT_BASE_FACTOR * pnl_coefficient - self.assertAlmostEqual(exit_reward, expected_base_exit - expected_potential, places=5) env.step(1) _, _, done, truncated, info = env.step(0) diff --git a/ReforceXY/tests/test_training_observations.py b/ReforceXY/tests/test_training_observations.py index 6fa931a..c3da5c1 100644 --- a/ReforceXY/tests/test_training_observations.py +++ b/ReforceXY/tests/test_training_observations.py @@ -8,6 +8,7 @@ from unittest import mock import numpy as np import pandas as pd +from freqtrade.enums import RunMode from freqtrade.exceptions import DependencyException from freqtrade.freqai.data_drawer import FreqaiDataDrawer from freqtrade.freqai.data_kitchen import FreqaiDataKitchen @@ -120,6 +121,89 @@ class TrainingObservationsTest(unittest.TestCase): ) self.assertTrue(np.isfinite(score)) + def test_backtest_rejects_future_archive_but_continues_from_earlier_saved_window(self): + with tempfile.TemporaryDirectory() as temp: + config = model_config(temp) + info = config["freqai"] + info["continual_learning"] = True + info["rl_config"]["model_type"] = "DQN" + info["model_training_parameters"] = { + "learning_starts": 0, + "buffer_size": 128, + "batch_size": 8, + "train_freq": 4, + "gradient_steps": 1, + "device": "cpu", + "policy_kwargs": {"net_arch": [8]}, + } + pair = "BTC/USDT" + + def frame(day, feature_offset): + values = np.arange(64) + data = pd.DataFrame( + { + "date": pd.date_range(day, periods=64, freq="5min", tz="UTC"), + "%-feature": np.sin(values) + feature_offset, + "&-action": np.zeros(64), + } + ) + for column in ("open", "high", "low", "close"): + data[f"%-raw_{column}"] = 100.0 + values * 0.1 + return data + + def kitchen(settings, data, *, live): + dk = FreqaiDataKitchen(settings, live=live, pair=pair) + timestamp = int((data["date"].iloc[-1] + pd.Timedelta(minutes=5)).timestamp()) + dk.set_paths(pair, timestamp) + dk.set_new_model_names(pair, timestamp) + dk.data_path.mkdir(parents=True, exist_ok=True) + dk.label_list = ["&-action"] + dk.training_features_list = [column for column in data if column.startswith("%")] + return dk, timestamp + + source = ReforceXY(config=config) + source.live = True + source.can_short = False + self.addCleanup(source.close_envs) + future = frame("2026-02-01", 1000.0) + future_dk, future_ts = kitchen(config, future, live=True) + deployed = source.train(future, pair, future_dk) + source.dd.get_pair_dict_info(pair) + source.dd.pair_dict[pair]["trained_timestamp"] = future_ts + source.dd.save_data(deployed, pair, future_dk) + + backtest_config = dict(config) + backtest_config["runmode"] = RunMode.BACKTEST + backtest_config["timerange"] = "20260101-20260105" + backtest_config["config_files"] = [ + "/workspace/ReforceXY/user_data/config-template.json" + ] + backtest = ReforceXY(config=backtest_config) + backtest.live = False + backtest.can_short = False + self.addCleanup(backtest.close_envs) + for day, offset, save_model in ( + ("2026-01-01", 0.0, False), + ("2026-01-02", 10.0, True), + ("2026-01-03", 20.0, False), + ): + training_frame = frame(day, offset) + dk, timestamp = kitchen(backtest_config, training_frame, live=False) + self.assertLess(timestamp, future_ts) + self.assertFalse(backtest.model_exists(dk)) + trained = backtest.train(training_frame, pair, dk) + transformed = dk.data_dictionary["train_features"]["%-feature"] + if offset < 20.0: + self.assertAlmostEqual(transformed.min(), -1.0) + self.assertAlmostEqual(transformed.max(), 1.0) + else: + self.assertGreater(transformed.min(), 2.0) + backtest.dd.pair_dict[pair]["trained_timestamp"] = timestamp + if save_model: + backtest.dd.save_data(trained, pair, dk) + else: + backtest.dd.save_metadata(dk) + def test_provenance_does_not_change_other_drawers(self): with tempfile.TemporaryDirectory() as temp: config = model_config(temp) diff --git a/ReforceXY/user_data/freqaimodels/ReforceXY.py b/ReforceXY/user_data/freqaimodels/ReforceXY.py index f12d205..8535a95 100644 --- a/ReforceXY/user_data/freqaimodels/ReforceXY.py +++ b/ReforceXY/user_data/freqaimodels/ReforceXY.py @@ -1281,7 +1281,7 @@ class ReforceXY(BaseReinforcementLearningModel): return callbacks def _resolve_deployment_state( - self, dk: FreqaiDataKitchen, pair: str + self, dk: FreqaiDataKitchen, pair: str, *, as_of_ts: int | None = None ) -> tuple[Any, Pipeline] | None: """Restore independent training copies of the deployed policy and feature pipeline.""" if not self.continual_learning: @@ -1291,6 +1291,19 @@ class ReforceXY(BaseReinforcementLearningModel): previous = self.dd.pair_dict.get(pair, {}) if model is None and not previous.get("model_filename"): return None + if not self.live: + # The drawer timestamp may advance without saving a new policy. + # Bound the actual artifact before loading policy, pipeline or replay. + name, separator, timestamp = previous.get("model_filename", "").rpartition("_") + if ( + as_of_ts is None + or not previous.get("trained_timestamp") + or not separator + or name != f"cb_{pair.split('/')[0].lower()}" + or not timestamp.isdecimal() + or int(timestamp) >= as_of_ts + ): + return None try: cached = self.dd.meta_data_dictionary.get(pair, {}) metadata = cached.get(METADATA) @@ -1432,7 +1445,16 @@ class ReforceXY(BaseReinforcementLearningModel): dk.fit_labels() # Capture prices once, before normalization and optional raw-OHLC removal. prices_train, prices_test = self.build_ohlc_price_dataframes(raw_data, pair, dk) - deployment_state = self._resolve_deployment_state(dk, pair) + as_of_ts = None + if self.continual_learning and not self.live: + latest_date = pd.to_datetime(unfiltered_df["date"], utc=True).max() + as_of_ts = int(latest_date.timestamp()) + 60 * timeframe_to_minutes( + self.config["timeframe"] + ) + training_timerange = getattr(self, "training_timerange", None) + if training_timerange is not None: + as_of_ts = min(as_of_ts, int(training_timerange.stopts)) + deployment_state = self._resolve_deployment_state(dk, pair, as_of_ts=as_of_ts) dd = self._apply_training_pipeline( raw_data, dk, deployment_state=None if self.hyperopt else deployment_state ) @@ -4114,6 +4136,9 @@ class MyRLEnv(Base5ActionRLEnv): reward = self.calculate_reward(action) trade_type = self.execute_trade(action) entry_pnl = self.get_unrealized_profit() if previous_position == Positions.Neutral else 0.0 + if trade_type is not None and self._position in (Positions.Long, Positions.Short): + self._update_max_unrealized_profit(entry_pnl) + self._update_min_unrealized_profit(entry_pnl) if trade_type is not None: self.append_trade_history( trade_type, self.current_price(), pre_pnl, execution_tick=execution_tick @@ -4189,7 +4214,7 @@ class MyRLEnv(Base5ActionRLEnv): f"{closed_position.name}_exit", self.current_price(), terminal_pnl, - execution_tick=execution_tick, + execution_tick=self._current_tick, ) if terminated: reward = self._apply_terminal_pbrs_correction(reward) diff --git a/quickadapter/.basedpyright/diagnostics.json b/quickadapter/.basedpyright/diagnostics.json index 0684d8a..fe96aa3 100644 --- a/quickadapter/.basedpyright/diagnostics.json +++ b/quickadapter/.basedpyright/diagnostics.json @@ -243,503 +243,503 @@ }, { "endCharacter": 87, - "endLine": 2602, + "endLine": 2621, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 82, - "startLine": 2602 + "startLine": 2621 }, { "endCharacter": 68, - "endLine": 2603, + "endLine": 2622, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 63, - "startLine": 2603 + "startLine": 2622 }, { "endCharacter": 63, - "endLine": 2614, + "endLine": 2633, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 58, - "startLine": 2614 + "startLine": 2633 }, { "endCharacter": 47, - "endLine": 2616, + "endLine": 2635, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"loc\" for class \"NDArray[Unknown]\"\n  Attribute \"loc\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 44, - "startLine": 2616 + "startLine": 2635 }, { "endCharacter": 47, - "endLine": 2616, + "endLine": 2635, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"loc\" for class \"list[Unknown]\"\n  Attribute \"loc\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 44, - "startLine": 2616 + "startLine": 2635 }, { "endCharacter": 43, - "endLine": 2617, + "endLine": 2636, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"loc\" for class \"NDArray[Unknown]\"\n  Attribute \"loc\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 40, - "startLine": 2617 + "startLine": 2636 }, { "endCharacter": 43, - "endLine": 2617, + "endLine": 2636, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"loc\" for class \"list[Unknown]\"\n  Attribute \"loc\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 40, - "startLine": 2617 + "startLine": 2636 }, { "endCharacter": 31, - "endLine": 2638, + "endLine": 2657, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"NDArray[Unknown]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 26, - "startLine": 2638 + "startLine": 2657 }, { "endCharacter": 31, - "endLine": 2638, + "endLine": 2657, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"list[Unknown]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 26, - "startLine": 2638 + "startLine": 2657 }, { "endCharacter": 60, - "endLine": 2638, + "endLine": 2657, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"NDArray[Unknown]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 55, - "startLine": 2638 + "startLine": 2657 }, { "endCharacter": 60, - "endLine": 2638, + "endLine": 2657, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"list[Unknown]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 55, - "startLine": 2638 + "startLine": 2657 }, { "endCharacter": 73, - "endLine": 2650, + "endLine": 2669, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" cannot be assigned to parameter \"target\" of type \"Index[Any]\" in function \"get_indexer\"\n  Type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" is not assignable to type \"Index[Any]\"\n    \"MethodType\" is not assignable to \"Index[Any]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 53, - "startLine": 2650 + "startLine": 2669 }, { "endCharacter": 73, - "endLine": 2650, + "endLine": 2669, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 68, - "startLine": 2650 + "startLine": 2669 }, { "endCharacter": 83, - "endLine": 2651, + "endLine": 2670, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" cannot be assigned to parameter \"target\" of type \"Index[Any]\" in function \"get_indexer\"\n  Type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" is not assignable to type \"Index[Any]\"\n    \"MethodType\" is not assignable to \"Index[Any]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 58, - "startLine": 2651 + "startLine": 2670 }, { "endCharacter": 83, - "endLine": 2651, + "endLine": 2670, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 78, - "startLine": 2651 + "startLine": 2670 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"Buffer\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"_NestedSequence[complex | bytes | str]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"_SupportsArray[dtype[Any]]\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"bytes\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"complex\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 46, - "endLine": 2886, + "endLine": 2905, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Cannot access attribute \"empty\" for class \"str\"\n  Attribute \"empty\" is unknown", "rule": "reportAttributeAccessIssue", "severity": "error", "startCharacter": 41, - "startLine": 2886 + "startLine": 2905 }, { "endCharacter": 41, - "endLine": 2893, + "endLine": 2912, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"ArrayLike\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_sanitize_pipeline_weights\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 16, - "startLine": 2893 + "startLine": 2912 }, { "endCharacter": 39, - "endLine": 2942, + "endLine": 2961, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"ArrayLike\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_sanitize_pipeline_weights\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 2942 + "startLine": 2961 }, { "endCharacter": 19, - "endLine": 3052, + "endLine": 3071, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"int | Any | None\" cannot be assigned to parameter \"gap\" of type \"int\" in function \"__init__\"\n  Type \"int | Any | None\" is not assignable to type \"int\"\n    \"None\" is not assignable to \"int\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 16, - "startLine": 3052 + "startLine": 3071 }, { "endCharacter": 21, - "endLine": 3164, + "endLine": 3183, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3164 + "startLine": 3183 }, { "endCharacter": 21, - "endLine": 3165, + "endLine": 3184, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3165 + "startLine": 3184 }, { "endCharacter": 33, - "endLine": 3166, + "endLine": 3185, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"train_weights\" of type \"NDArray[floating[Any]]\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3166 + "startLine": 3185 }, { "endCharacter": 32, - "endLine": 3167, + "endLine": 3186, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X_validation\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3167 + "startLine": 3186 }, { "endCharacter": 32, - "endLine": 3168, + "endLine": 3187, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y_validation\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3168 + "startLine": 3187 }, { "endCharacter": 38, - "endLine": 3169, + "endLine": 3188, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"validation_weights\" of type \"NDArray[floating[Any]]\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 20, - "startLine": 3169 + "startLine": 3188 }, { "endCharacter": 24, - "endLine": 3190, + "endLine": 3209, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X_test\" of type \"DataFrame\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 12, - "startLine": 3190 + "startLine": 3209 }, { "endCharacter": 24, - "endLine": 3191, + "endLine": 3210, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y_test\" of type \"DataFrame\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 12, - "startLine": 3191 + "startLine": 3210 }, { "endCharacter": 30, - "endLine": 3192, + "endLine": 3211, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"test_weights\" of type \"NDArray[floating[Any]]\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 12, - "startLine": 3192 + "startLine": 3211 }, { "endCharacter": 15, - "endLine": 3198, + "endLine": 3217, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X\" of type \"DataFrame\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 14, - "startLine": 3198 + "startLine": 3217 }, { "endCharacter": 15, - "endLine": 3199, + "endLine": 3218, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y\" of type \"DataFrame\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 14, - "startLine": 3199 + "startLine": 3218 }, { "endCharacter": 39, - "endLine": 3200, + "endLine": 3219, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"train_weights\" of type \"NDArray[floating[Any]]\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 26, - "startLine": 3200 + "startLine": 3219 }, { "endCharacter": 38, - "endLine": 3210, + "endLine": 3229, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "\"columns\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 31, - "startLine": 3210 + "startLine": 3229 }, { "endCharacter": 34, - "endLine": 3211, + "endLine": 3230, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "\"index\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 29, - "startLine": 3211 + "startLine": 3230 }, { "endCharacter": 82, - "endLine": 3213, + "endLine": 3232, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "\"copy\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 78, - "startLine": 3213 + "startLine": 3232 }, { "endCharacter": 62, - "endLine": 3647, + "endLine": 3666, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "\"get_pair_dataframe\" is not a known attribute of \"None\"", "rule": "reportOptionalMemberAccess", "severity": "error", "startCharacter": 44, - "startLine": 3647 + "startLine": 3666 }, { "endCharacter": 68, - "endLine": 4027, + "endLine": 4046, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Type \"floating[Any] | NDArray[float64]\" is not assignable to return type \"NDArray[floating[Any]]\"\n  Type \"floating[Any] | NDArray[float64]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"floating[Any]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"", "rule": "reportReturnType", "severity": "error", "startCharacter": 15, - "startLine": 4023 + "startLine": 4042 }, { "endCharacter": 13, - "endLine": 4056, + "endLine": 4075, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "No overloads for \"cdist\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 19, - "startLine": 4051 + "startLine": 4070 }, { "endCharacter": 38, - "endLine": 4054, + "endLine": 4073, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"cdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 23, - "startLine": 4054 + "startLine": 4073 }, { "endCharacter": 9, - "endLine": 4159, + "endLine": 4178, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "No overloads for \"pdist\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 36, - "startLine": 4157 + "startLine": 4176 }, { "endCharacter": 42, - "endLine": 4158, + "endLine": 4177, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"pdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 27, - "startLine": 4158 + "startLine": 4177 }, { "endCharacter": 9, - "endLine": 4236, + "endLine": 4255, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "No overloads for \"cdist\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 15, - "startLine": 4231 + "startLine": 4250 }, { "endCharacter": 34, - "endLine": 4234, + "endLine": 4253, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"cdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 19, - "startLine": 4234 + "startLine": 4253 }, { "endCharacter": 99, - "endLine": 4425, + "endLine": 4444, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "No overloads for \"pdist\" match the provided arguments", "rule": "reportCallIssue", "severity": "error", "startCharacter": 12, - "startLine": 4425 + "startLine": 4444 }, { "endCharacter": 79, - "endLine": 4425, + "endLine": 4444, "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py", "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"pdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"", "rule": "reportArgumentType", "severity": "error", "startCharacter": 64, - "startLine": 4425 + "startLine": 4444 }, { "endCharacter": 55, diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index 623a22b..d5d5b77 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -2372,7 +2372,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): ) def _resolve_deployment_state( - self, dk: FreqaiDataKitchen, pair: str + self, dk: FreqaiDataKitchen, pair: str, *, as_of_ts: int | None = None ) -> tuple[Any, Pipeline, Pipeline] | None: """Restore the deployed model with independent copies of its fitted pipelines.""" if not self.continual_learning: @@ -2401,6 +2401,19 @@ class QuickAdapterRegressorV3(BaseRegressionModel): previous = self.dd.pair_dict.get(pair, {}) if model is None and not previous.get("model_filename"): return None + if not self.live: + # The drawer timestamp can advance without saving a model. Bound the + # actual artifact instead, before reading cached or persisted state. + name, separator, timestamp = previous.get("model_filename", "").rpartition("_") + if ( + as_of_ts is None + or not previous.get("trained_timestamp") + or not separator + or name != f"cb_{pair.split('/')[0].lower()}" + or not timestamp.isdecimal() + or int(timestamp) >= as_of_ts + ): + return None try: cached = self.dd.meta_data_dictionary.get(pair) if model is not None and cached is not None: @@ -2499,7 +2512,13 @@ class QuickAdapterRegressorV3(BaseRegressionModel): ) if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live: dk.fit_labels() - deployment_state = self._resolve_deployment_state(dk, pair) + as_of_ts = None + if self.continual_learning and not self.live: + as_of_ts = int(dates.max().timestamp()) + timeframe_to_seconds(self.config["timeframe"]) + training_timerange = getattr(self, "training_timerange", None) + if training_timerange is not None: + as_of_ts = min(as_of_ts, int(training_timerange.stopts)) + deployment_state = self._resolve_deployment_state(dk, pair, as_of_ts=as_of_ts) dd = self._apply_pipelines( dd, train_weight_inputs, -- 2.53.0