},
{
"endCharacter": 55,
- "endLine": 225,
+ "endLine": 226,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Type \"int\" is not assignable to declared type \"cached_property[int]\"\n \"int\" is not assignable to \"cached_property[int]\"",
"rule": "reportAssignmentType",
"severity": "error",
"startCharacter": 24,
- "startLine": 225
+ "startLine": 226
},
{
"endCharacter": 15,
- "endLine": 269,
+ "endLine": 261,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Class variable \"minimal_roi\" overrides instance variable of same name in class \"IStrategy\"",
"rule": "reportIncompatibleVariableOverride",
"severity": "error",
"startCharacter": 4,
- "startLine": 269
+ "startLine": 261
},
{
"endCharacter": 72,
- "endLine": 269,
+ "endLine": 261,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"*\" not supported for types \"cached_property[int]\" and \"Literal[864]\"",
"rule": "reportOperatorIssue",
"severity": "error",
"startCharacter": 49,
- "startLine": 269
+ "startLine": 261
},
{
"endCharacter": 64,
- "endLine": 282,
+ "endLine": 274,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"timeframe_to_minutes\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 36,
- "startLine": 282
+ "startLine": 274
},
{
"endCharacter": 17,
- "endLine": 291,
+ "endLine": 283,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"can_short\" overrides symbol of same name in class \"IStrategy\"\n \"property\" is not assignable to \"bool\"",
"rule": "reportIncompatibleVariableOverride",
"severity": "error",
"startCharacter": 8,
- "startLine": 291
+ "startLine": 283
},
{
"endCharacter": 19,
- "endLine": 295,
+ "endLine": 287,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"plot_config\" overrides symbol of same name in class \"IStrategy\"\n \"cached_property[dict[str, Any]]\" is not assignable to \"dict[Unknown, Unknown]\"",
"rule": "reportIncompatibleVariableOverride",
"severity": "error",
"startCharacter": 8,
- "startLine": 295
+ "startLine": 287
},
{
"endCharacter": 19,
- "endLine": 339,
+ "endLine": 331,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"protections\" overrides symbol of same name in class \"IStrategy\"\n \"cached_property[list[dict[str, Any]]]\" is not assignable to \"list[Unknown]\"",
"rule": "reportIncompatibleVariableOverride",
"severity": "error",
"startCharacter": 8,
- "startLine": 339
+ "startLine": 331
},
{
"endCharacter": 28,
- "endLine": 412,
+ "endLine": 404,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"startup_candle_count\" overrides symbol of same name in class \"IStrategy\"\n \"property\" is not assignable to \"int\"",
"rule": "reportIncompatibleVariableOverride",
"severity": "error",
"startCharacter": 8,
- "startLine": 412
+ "startLine": 404
},
{
"endCharacter": 44,
- "endLine": 491,
+ "endLine": 513,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"/\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 12,
- "startLine": 491
+ "startLine": 513
},
{
"endCharacter": 38,
- "endLine": 766,
+ "endLine": 787,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 30,
- "startLine": 766
+ "startLine": 787
},
{
"endCharacter": 44,
- "endLine": 799,
+ "endLine": 820,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"-\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 38,
- "startLine": 799
+ "startLine": 820
},
{
"endCharacter": 38,
- "endLine": 807,
+ "endLine": 828,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Object of type \"None\" is not subscriptable",
"rule": "reportOptionalSubscript",
"severity": "error",
"startCharacter": 36,
- "startLine": 807
+ "startLine": 828
},
{
"endCharacter": 39,
- "endLine": 808,
+ "endLine": 829,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Object of type \"None\" is not subscriptable",
"rule": "reportOptionalSubscript",
"severity": "error",
"startCharacter": 37,
- "startLine": 808
+ "startLine": 829
},
{
"endCharacter": 38,
- "endLine": 809,
+ "endLine": 830,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Object of type \"None\" is not subscriptable",
"rule": "reportOptionalSubscript",
"severity": "error",
"startCharacter": 36,
- "startLine": 809
+ "startLine": 830
},
{
"endCharacter": 44,
- "endLine": 832,
+ "endLine": 853,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"-\" not supported for types \"Series[Any] | None\" and \"Series[Any] | None\"\n Operator \"-\" not supported for types \"Series[Any]\" and \"None\"\n Operator \"-\" not supported for types \"None\" and \"Series[Any]\"\n Operator \"-\" not supported for types \"None\" and \"None\"",
"rule": "reportOperatorIssue",
"severity": "error",
"startCharacter": 29,
- "startLine": 832
+ "startLine": 853
},
{
"endCharacter": 66,
- "endLine": 832,
+ "endLine": 853,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"s1\" of type \"Series[Any]\" in function \"non_zero_diff\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 61,
- "startLine": 832
+ "startLine": 853
},
{
"endCharacter": 72,
- "endLine": 832,
+ "endLine": 853,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"s2\" of type \"Series[Any]\" in function \"non_zero_diff\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 68,
- "startLine": 832
+ "startLine": 853
},
{
"endCharacter": 56,
- "endLine": 838,
+ "endLine": 859,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 50,
- "startLine": 838
+ "startLine": 859
},
{
"endCharacter": 58,
- "endLine": 839,
+ "endLine": 860,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 52,
- "startLine": 839
+ "startLine": 860
},
{
"endCharacter": 57,
- "endLine": 840,
+ "endLine": 861,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 51,
- "startLine": 840
+ "startLine": 861
},
{
"endCharacter": 44,
- "endLine": 843,
+ "endLine": 864,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 38,
- "startLine": 843
+ "startLine": 864
},
{
"endCharacter": 44,
- "endLine": 844,
+ "endLine": 865,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 38,
- "startLine": 844
+ "startLine": 865
},
{
"endCharacter": 44,
- "endLine": 845,
+ "endLine": 866,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 38,
- "startLine": 845
+ "startLine": 866
},
{
"endCharacter": 61,
- "endLine": 846,
+ "endLine": 867,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 55,
- "startLine": 846
+ "startLine": 867
},
{
"endCharacter": 61,
- "endLine": 847,
+ "endLine": 868,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 55,
- "startLine": 847
+ "startLine": 868
},
{
"endCharacter": 61,
- "endLine": 848,
+ "endLine": 869,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 55,
- "startLine": 848
+ "startLine": 869
},
{
"endCharacter": 81,
- "endLine": 856,
+ "endLine": 877,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any]\" cannot be assigned to parameter \"p2\" of type \"T@get_distance\" in function \"get_distance\"\n \"Series[Any]\" is not assignable to \"float\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 58,
- "startLine": 856
+ "startLine": 877
},
{
"endCharacter": 67,
- "endLine": 869,
+ "endLine": 890,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 61,
- "startLine": 869
+ "startLine": 890
},
{
"endCharacter": 68,
- "endLine": 870,
+ "endLine": 891,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 62,
- "startLine": 870
+ "startLine": 891
},
{
"endCharacter": 67,
- "endLine": 871,
+ "endLine": 892,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 61,
- "startLine": 871
+ "startLine": 892
},
{
"endCharacter": 44,
- "endLine": 872,
+ "endLine": 893,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"-\" not supported for types \"Series[Any] | None\" and \"Series[Any] | None\"\n Operator \"-\" not supported for types \"Series[Any]\" and \"None\" when expected type is \"_SetItemValueNotDataFrame\"\n Operator \"-\" not supported for types \"None\" and \"Series[Any]\" when expected type is \"_SetItemValueNotDataFrame\"\n Operator \"-\" not supported for types \"None\" and \"None\" when expected type is \"_SetItemValueNotDataFrame\"",
"rule": "reportOperatorIssue",
"severity": "error",
"startCharacter": 30,
- "startLine": 872
+ "startLine": 893
},
{
"endCharacter": 56,
- "endLine": 873,
+ "endLine": 894,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "No overloads for \"__call__\" match the provided arguments",
"rule": "reportCallIssue",
"severity": "error",
"startCharacter": 31,
- "startLine": 873
+ "startLine": 894
},
{
"endCharacter": 47,
- "endLine": 873,
+ "endLine": 894,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x1\" of type \"ArrayLike\" in function \"__call__\"\n Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n Type \"None\" is not assignable to type \"ArrayLike\"\n \"None\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n \"__array__\" is not present\n \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n \"__len__\" is not present\n ...",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 42,
- "startLine": 873
+ "startLine": 894
},
{
"endCharacter": 55,
- "endLine": 873,
+ "endLine": 894,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x2\" of type \"ArrayLike\" in function \"__call__\"\n Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n Type \"None\" is not assignable to type \"ArrayLike\"\n \"None\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n \"__array__\" is not present\n \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n \"__len__\" is not present\n ...",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 873
+ "startLine": 894
},
{
"endCharacter": 64,
- "endLine": 874,
+ "endLine": 895,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "No overloads for \"__call__\" match the provided arguments",
"rule": "reportCallIssue",
"severity": "error",
"startCharacter": 39,
- "startLine": 874
+ "startLine": 895
},
{
"endCharacter": 55,
- "endLine": 874,
+ "endLine": 895,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x1\" of type \"ArrayLike\" in function \"__call__\"\n Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n Type \"None\" is not assignable to type \"ArrayLike\"\n \"None\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n \"__array__\" is not present\n \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n \"__len__\" is not present\n ...",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 50,
- "startLine": 874
+ "startLine": 895
},
{
"endCharacter": 63,
- "endLine": 874,
+ "endLine": 895,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x2\" of type \"ArrayLike\" in function \"__call__\"\n Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n Type \"None\" is not assignable to type \"ArrayLike\"\n \"None\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n \"__array__\" is not present\n \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n \"__len__\" is not present\n ...",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 57,
- "startLine": 874
+ "startLine": 895
},
{
"endCharacter": 55,
- "endLine": 882,
+ "endLine": 903,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 882
+ "startLine": 903
},
{
"endCharacter": 55,
- "endLine": 883,
+ "endLine": 904,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 883
+ "startLine": 904
},
{
"endCharacter": 55,
- "endLine": 884,
+ "endLine": 905,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 884
+ "startLine": 905
},
{
"endCharacter": 55,
- "endLine": 885,
+ "endLine": 906,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 885
+ "startLine": 906
},
{
"endCharacter": 55,
- "endLine": 886,
+ "endLine": 907,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 886
+ "startLine": 907
},
{
"endCharacter": 55,
- "endLine": 887,
+ "endLine": 908,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 49,
- "startLine": 887
+ "startLine": 908
},
{
"endCharacter": 50,
- "endLine": 916,
+ "endLine": 937,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 44,
- "startLine": 916
+ "startLine": 937
},
{
"endCharacter": 50,
- "endLine": 916,
+ "endLine": 937,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 44,
- "startLine": 916
+ "startLine": 937
},
{
"endCharacter": 29,
- "endLine": 917,
+ "endLine": 938,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 23,
- "startLine": 917
+ "startLine": 938
},
{
"endCharacter": 29,
- "endLine": 917,
+ "endLine": 938,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 23,
- "startLine": 917
+ "startLine": 938
},
{
"endCharacter": 60,
- "endLine": 954,
+ "endLine": 975,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 50,
- "startLine": 954
+ "startLine": 975
},
{
"endCharacter": 60,
- "endLine": 954,
+ "endLine": 975,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 50,
- "startLine": 954
+ "startLine": 975
},
{
"endCharacter": 35,
- "endLine": 955,
+ "endLine": 976,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 25,
- "startLine": 955
+ "startLine": 976
},
{
"endCharacter": 35,
- "endLine": 955,
+ "endLine": 976,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 25,
- "startLine": 955
+ "startLine": 976
},
{
"endCharacter": 41,
- "endLine": 1180,
+ "endLine": 1201,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"<\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 12,
- "startLine": 1180
+ "startLine": 1201
},
{
"endCharacter": 41,
- "endLine": 1190,
+ "endLine": 1211,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \">\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 12,
- "startLine": 1190
+ "startLine": 1211
},
{
"endCharacter": 66,
- "endLine": 1203,
+ "endLine": 1224,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"timeframe_to_prev_date\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 38,
- "startLine": 1203
+ "startLine": 1224
},
{
"endCharacter": 70,
- "endLine": 1334,
+ "endLine": 1355,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Expected 1 more positional argument",
"rule": "reportCallIssue",
"severity": "error",
"startCharacter": 48,
- "startLine": 1334
+ "startLine": 1355
},
{
"endCharacter": 74,
- "endLine": 1398,
+ "endLine": 1419,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"int | None\" cannot be assigned to parameter \"trade_duration_candles\" of type \"int\" in function \"get_trade_natr\"\n Type \"int | None\" is not assignable to type \"int\"\n \"None\" is not assignable to \"int\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 52,
- "startLine": 1398
+ "startLine": 1419
},
{
"endCharacter": 74,
- "endLine": 1425,
+ "endLine": 1446,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"int | None\" cannot be assigned to parameter \"trade_duration_candles\" of type \"int\" in function \"get_trade_natr\"\n Type \"int | None\" is not assignable to type \"int\"\n \"None\" is not assignable to \"int\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 52,
- "startLine": 1425
+ "startLine": 1446
},
{
"endCharacter": 96,
- "endLine": 1477,
+ "endLine": 1498,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 68,
- "startLine": 1477
+ "startLine": 1498
},
{
"endCharacter": 77,
- "endLine": 1507,
+ "endLine": 1528,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"<=\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 57,
- "startLine": 1507
+ "startLine": 1528
},
{
"endCharacter": 9,
- "endLine": 1512,
+ "endLine": 1533,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"+\" not supported for types \"float\" and \"float | None\"\n Operator \"+\" not supported for types \"float\" and \"None\"",
"rule": "reportOperatorIssue",
"severity": "error",
"startCharacter": 28,
- "startLine": 1510
+ "startLine": 1531
},
{
"endCharacter": 33,
- "endLine": 1511,
+ "endLine": 1532,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"-\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 13,
- "startLine": 1511
+ "startLine": 1532
},
{
"endCharacter": 67,
- "endLine": 1517,
+ "endLine": 1538,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 47,
- "startLine": 1517
+ "startLine": 1538
},
{
"endCharacter": 67,
- "endLine": 1517,
+ "endLine": 1538,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.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": 47,
- "startLine": 1517
+ "startLine": 1538
},
{
"endCharacter": 64,
- "endLine": 1671,
+ "endLine": 1692,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"isoformat\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 55,
- "startLine": 1671
+ "startLine": 1692
},
{
"endCharacter": 37,
- "endLine": 1722,
+ "endLine": 1743,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"<=\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 15,
- "startLine": 1722
+ "startLine": 1743
},
{
"endCharacter": 48,
- "endLine": 1724,
+ "endLine": 1745,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"<=\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 15,
- "startLine": 1724
+ "startLine": 1745
},
{
"endCharacter": 96,
- "endLine": 1904,
+ "endLine": 1925,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 68,
- "startLine": 1904
+ "startLine": 1925
},
{
"endCharacter": 39,
- "endLine": 1981,
+ "endLine": 2028,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"+\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 21,
- "startLine": 1981
+ "startLine": 2028
},
{
"endCharacter": 90,
- "endLine": 1981,
+ "endLine": 2028,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"*\" not supported for types \"float\" and \"Any | None\"\n Operator \"*\" not supported for types \"float\" and \"None\"",
"rule": "reportOperatorIssue",
"severity": "error",
"startCharacter": 62,
- "startLine": 1981
+ "startLine": 2028
},
{
"endCharacter": 96,
- "endLine": 2285,
+ "endLine": 2332,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 68,
- "startLine": 2285
+ "startLine": 2332
},
{
"endCharacter": 85,
- "endLine": 2310,
+ "endLine": 2357,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "\"isoformat\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 76,
- "startLine": 2310
+ "startLine": 2357
},
{
"endCharacter": 47,
- "endLine": 2316,
+ "endLine": 2363,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \"<\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 16,
- "startLine": 2316
+ "startLine": 2363
},
{
"endCharacter": 42,
- "endLine": 2320,
+ "endLine": 2367,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"side\" of type \"TradeDirection\" in function \"reversal_confirmed\"\n Type \"str\" is not assignable to type \"TradeDirection\"\n \"str\" is not assignable to type \"Literal['long']\"\n \"str\" is not assignable to type \"Literal['short']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2320
+ "startLine": 2367
},
{
"endCharacter": 42,
- "endLine": 2321,
+ "endLine": 2368,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n Type \"str\" is not assignable to type \"OrderType\"\n \"str\" is not assignable to type \"Literal['entry']\"\n \"str\" is not assignable to type \"Literal['exit']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2321
+ "startLine": 2368
},
{
"endCharacter": 69,
- "endLine": 2323,
+ "endLine": 2370,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n Type \"int | float\" is not assignable to type \"int\"\n \"float\" is not assignable to \"int\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2323
+ "startLine": 2370
},
{
"endCharacter": 47,
- "endLine": 2334,
+ "endLine": 2381,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Operator \">\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 16,
- "startLine": 2334
+ "startLine": 2381
},
{
"endCharacter": 43,
- "endLine": 2338,
+ "endLine": 2385,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"side\" of type \"TradeDirection\" in function \"reversal_confirmed\"\n Type \"str\" is not assignable to type \"TradeDirection\"\n \"str\" is not assignable to type \"Literal['long']\"\n \"str\" is not assignable to type \"Literal['short']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2338
+ "startLine": 2385
},
{
"endCharacter": 42,
- "endLine": 2339,
+ "endLine": 2386,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n Type \"str\" is not assignable to type \"OrderType\"\n \"str\" is not assignable to type \"Literal['entry']\"\n \"str\" is not assignable to type \"Literal['exit']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2339
+ "startLine": 2386
},
{
"endCharacter": 69,
- "endLine": 2341,
+ "endLine": 2388,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n Type \"int | float\" is not assignable to type \"int\"\n \"float\" is not assignable to \"int\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2341
+ "startLine": 2388
},
{
"endCharacter": 52,
- "endLine": 2370,
+ "endLine": 2417,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"datetime | None\" cannot be assigned to parameter \"current_candle_date\" of type \"datetime\" in function \"_normalize_final_take_profit_state\"\n Type \"datetime | None\" is not assignable to type \"datetime\"\n \"None\" is not assignable to \"datetime\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 36,
- "startLine": 2370
+ "startLine": 2417
},
{
"endCharacter": 96,
- "endLine": 2490,
+ "endLine": 2537,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n Type \"Any | None\" is not assignable to type \"str\"\n \"None\" is not assignable to \"str\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 68,
- "startLine": 2490
+ "startLine": 2537
},
{
"endCharacter": 43,
- "endLine": 2499,
+ "endLine": 2546,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n Type \"str\" is not assignable to type \"OrderType\"\n \"str\" is not assignable to type \"Literal['entry']\"\n \"str\" is not assignable to type \"Literal['exit']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2499
+ "startLine": 2546
},
{
"endCharacter": 69,
- "endLine": 2501,
+ "endLine": 2548,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n Type \"int | float\" is not assignable to type \"int\"\n \"float\" is not assignable to \"int\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 2501
+ "startLine": 2548
},
{
"endCharacter": 32,
- "endLine": 2577,
+ "endLine": 2624,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_annotation_line_start_date\"\n \"LocalTrade\" is not assignable to \"Trade\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 27,
- "startLine": 2577
+ "startLine": 2624
},
{
"endCharacter": 72,
- "endLine": 2580,
+ "endLine": 2627,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_exit_stage\"\n \"LocalTrade\" is not assignable to \"Trade\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 67,
- "startLine": 2580
+ "startLine": 2627
},
{
"endCharacter": 36,
- "endLine": 2587,
+ "endLine": 2634,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_take_profit_target\"\n \"LocalTrade\" is not assignable to \"Trade\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 31,
- "startLine": 2587
+ "startLine": 2634
},
{
"endCharacter": 71,
- "endLine": 2618,
+ "endLine": 2665,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_entry_date\"\n \"LocalTrade\" is not assignable to \"Trade\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 66,
- "startLine": 2618
+ "startLine": 2665
},
{
"endCharacter": 32,
- "endLine": 2649,
+ "endLine": 2698,
"file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
"message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_take_profit_target\"\n \"LocalTrade\" is not assignable to \"Trade\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 27,
- "startLine": 2649
+ "startLine": 2698
},
{
"endCharacter": 35,
},
{
"endCharacter": 98,
- "endLine": 1710,
+ "endLine": 1725,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Type \"bool | bool_\" is not assignable to return type \"bool\"\n Type \"bool | bool_\" is not assignable to type \"bool\"\n \"numpy.bool[builtins.bool]\" is not assignable to \"bool\"",
"rule": "reportReturnType",
"severity": "error",
"startCharacter": 15,
- "startLine": 1710
+ "startLine": 1725
},
{
"endCharacter": 33,
- "endLine": 1744,
+ "endLine": 1759,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Scalar\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n Type \"Scalar\" is not assignable to type \"ConvertibleToInt\"\n Type \"complex\" is not assignable to type \"ConvertibleToInt\"\n \"complex\" is not assignable to \"str\"\n \"complex\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"complex\" is incompatible with protocol \"SupportsInt\"\n \"__int__\" is not present\n \"complex\" is incompatible with protocol \"SupportsIndex\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 20,
- "startLine": 1744
+ "startLine": 1759
},
{
"endCharacter": 33,
- "endLine": 1744,
+ "endLine": 1759,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Scalar\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n Type \"Scalar\" is not assignable to type \"ConvertibleToInt\"\n Type \"complex\" is not assignable to type \"ConvertibleToInt\"\n \"complex\" is not assignable to \"str\"\n \"complex\" is incompatible with protocol \"Buffer\"\n \"__buffer__\" is not present\n \"complex\" is incompatible with protocol \"SupportsInt\"\n \"__int__\" is not present\n \"complex\" is incompatible with protocol \"SupportsIndex\"\n ...",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 20,
- "startLine": 1744
+ "startLine": 1759
},
{
"endCharacter": 23,
- "endLine": 1756,
+ "endLine": 1771,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Type \"float\" is not assignable to return type \"T@get_distance\"\n Type \"float\" is not assignable to type \"T@get_distance\"",
"rule": "reportReturnType",
"severity": "error",
"startCharacter": 11,
- "startLine": 1756
+ "startLine": 1771
},
{
"endCharacter": 83,
- "endLine": 2609,
+ "endLine": 2624,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"str\" cannot be assigned to parameter \"key\" of type \"CombinedMetric\" in function \"__getitem__\"\n Type \"str\" is not assignable to type \"CombinedMetric\"\n \"str\" is not assignable to type \"Literal['amplitude']\"\n \"str\" is not assignable to type \"Literal['amplitude_threshold_ratio']\"\n \"str\" is not assignable to type \"Literal['volume_rate']\"\n \"str\" is not assignable to type \"Literal['speed']\"\n \"str\" is not assignable to type \"Literal['efficiency_ratio']\"\n \"str\" is not assignable to type \"Literal['volume_weighted_efficiency_ratio']\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 58,
- "startLine": 2609
+ "startLine": 2624
},
{
"endCharacter": 38,
- "endLine": 3499,
+ "endLine": 3514,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Cannot access attribute \"__func__\" for class \"FunctionType\"\n Attribute \"__func__\" is unknown",
"rule": "reportFunctionMemberAccess",
"severity": "error",
"startCharacter": 30,
- "startLine": 3499
+ "startLine": 3514
},
{
"endCharacter": 34,
- "endLine": 3501,
+ "endLine": 3516,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Cannot access attribute \"__func__\" for class \"FunctionType\"\n Attribute \"__func__\" is unknown",
"rule": "reportFunctionMemberAccess",
"severity": "error",
"startCharacter": 26,
- "startLine": 3501
+ "startLine": 3516
},
{
"endCharacter": 55,
- "endLine": 3731,
+ "endLine": 3746,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"rolling\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 48,
- "startLine": 3731
+ "startLine": 3746
},
{
"endCharacter": 38,
- "endLine": 3756,
+ "endLine": 3771,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"rolling\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 31,
- "startLine": 3756
+ "startLine": 3771
},
{
"endCharacter": 55,
- "endLine": 3782,
+ "endLine": 3797,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"rolling\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 48,
- "startLine": 3782
+ "startLine": 3797
},
{
"endCharacter": 56,
- "endLine": 3783,
+ "endLine": 3798,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"rolling\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 49,
- "startLine": 3783
+ "startLine": 3798
},
{
"endCharacter": 33,
- "endLine": 3855,
+ "endLine": 3870,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Series[Any] | NDArray[floating[Any]]\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n \"ndarray[_AnyShape, dtype[floating[Any]]]\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 27,
- "startLine": 3855
+ "startLine": 3870
},
{
"endCharacter": 69,
- "endLine": 3855,
+ "endLine": 3870,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Expected 1 more positional argument",
"rule": "reportCallIssue",
"severity": "error",
"startCharacter": 59,
- "startLine": 3855
+ "startLine": 3870
},
{
"endCharacter": 40,
- "endLine": 3922,
+ "endLine": 3937,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 35,
- "startLine": 3922
+ "startLine": 3937
},
{
"endCharacter": 38,
- "endLine": 3923,
+ "endLine": 3938,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 34,
- "startLine": 3923
+ "startLine": 3938
},
{
"endCharacter": 42,
- "endLine": 3924,
+ "endLine": 3939,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n \"None\" is not assignable to \"Series[Any]\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 36,
- "startLine": 3924
+ "startLine": 3939
},
{
"endCharacter": 45,
- "endLine": 3926,
+ "endLine": 3941,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"index\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 40,
- "startLine": 3926
+ "startLine": 3941
},
{
"endCharacter": 33,
- "endLine": 3928,
+ "endLine": 3943,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"iloc\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 29,
- "startLine": 3928
+ "startLine": 3943
},
{
"endCharacter": 31,
- "endLine": 3929,
+ "endLine": 3944,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"iloc\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 27,
- "startLine": 3929
+ "startLine": 3944
},
{
"endCharacter": 48,
- "endLine": 3934,
+ "endLine": 3949,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"index\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 43,
- "startLine": 3934
+ "startLine": 3949
},
{
"endCharacter": 40,
- "endLine": 3935,
+ "endLine": 3950,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"iloc\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 36,
- "startLine": 3935
+ "startLine": 3950
},
{
"endCharacter": 59,
- "endLine": 3937,
+ "endLine": 3952,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n Attribute \"iloc\" is unknown",
"rule": "reportAttributeAccessIssue",
"severity": "error",
"startCharacter": 55,
- "startLine": 3937
+ "startLine": 3952
},
{
"endCharacter": 34,
- "endLine": 3939,
+ "endLine": 3954,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n Attribute \"iloc\" is unknown",
"rule": "reportAttributeAccessIssue",
"severity": "error",
"startCharacter": 30,
- "startLine": 3939
+ "startLine": 3954
},
{
"endCharacter": 51,
- "endLine": 3939,
+ "endLine": 3954,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"iloc\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 47,
- "startLine": 3939
+ "startLine": 3954
},
{
"endCharacter": 72,
- "endLine": 3939,
+ "endLine": 3954,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n Attribute \"iloc\" is unknown",
"rule": "reportAttributeAccessIssue",
"severity": "error",
"startCharacter": 68,
- "startLine": 3939
+ "startLine": 3954
},
{
"endCharacter": 40,
- "endLine": 4006,
+ "endLine": 4021,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to declared type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n Missing keyword parameter \"series\"\n Missing keyword parameter \"timeperiod\"\n Position-only parameter mismatch; parameter \"series\" is not position-only\n Position-only parameter mismatch; parameter \"timeperiod\" is not position-only\n Position-only parameter mismatch; expected 2 but received 0\n Function return type \"Series[Any] | NDArray[floating[Any]]\" is incompatible with type \"Series[Any]\"\n Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n ...",
"rule": "reportAssignmentType",
"severity": "error",
"startCharacter": 20,
- "startLine": 4006
+ "startLine": 4021
},
{
"endCharacter": 33,
- "endLine": 4008,
+ "endLine": 4023,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to declared type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n Missing keyword parameter \"series\"\n Missing keyword parameter \"timeperiod\"\n Position-only parameter mismatch; parameter \"series\" is not position-only\n Position-only parameter mismatch; parameter \"timeperiod\" is not position-only\n Position-only parameter mismatch; expected 2 but received 0\n Function return type \"Series[Any] | NDArray[floating[Any]]\" is incompatible with type \"Series[Any]\"\n Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n ...",
"rule": "reportAssignmentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 4008
+ "startLine": 4023
},
{
"endCharacter": 35,
- "endLine": 4054,
+ "endLine": 4069,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 27,
- "startLine": 4054
+ "startLine": 4069
},
{
"endCharacter": 33,
- "endLine": 4055,
+ "endLine": 4070,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 25,
- "startLine": 4055
+ "startLine": 4070
},
{
"endCharacter": 37,
- "endLine": 4172,
+ "endLine": 4187,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 29,
- "startLine": 4172
+ "startLine": 4187
},
{
"endCharacter": 35,
- "endLine": 4173,
+ "endLine": 4188,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 27,
- "startLine": 4173
+ "startLine": 4188
},
{
"endCharacter": 33,
- "endLine": 4174,
+ "endLine": 4189,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 25,
- "startLine": 4174
+ "startLine": 4189
},
{
"endCharacter": 39,
- "endLine": 4194,
+ "endLine": 4209,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"to_numpy\" is not a known attribute of \"None\"",
"rule": "reportOptionalMemberAccess",
"severity": "error",
"startCharacter": 31,
- "startLine": 4194
+ "startLine": 4209
},
{
"endCharacter": 92,
- "endLine": 4553,
+ "endLine": 4568,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Type \"bool_ | bool\" is not assignable to return type \"bool\"\n Type \"bool_ | bool\" is not assignable to type \"bool\"\n \"numpy.bool[builtins.bool]\" is not assignable to \"bool\"",
"rule": "reportReturnType",
"severity": "error",
"startCharacter": 15,
- "startLine": 4553
+ "startLine": 4568
},
{
"endCharacter": 85,
- "endLine": 4954,
+ "endLine": 4969,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"XGBoostPruningCallback\" cannot be assigned to parameter \"object\" of type \"RegressorCallback\" in function \"append\"\n Type \"XGBoostPruningCallback\" is not assignable to type \"RegressorCallback\"\n Type \"XGBoostPruningCallback\" is not assignable to type \"(...) -> Any\"\n \"XGBoostPruningCallback\" is not assignable to \"TrainingCallback\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 16,
- "startLine": 4954
+ "startLine": 4969
},
{
"endCharacter": 29,
- "endLine": 4997,
+ "endLine": 5012,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"list[tuple[DataFrame, DataFrame]] | None\" cannot be assigned to parameter \"eval_set\" of type \"List[_LGBM_ScikitValidSet] | None\" in function \"fit\"\n Type \"list[tuple[DataFrame, DataFrame]] | None\" is not assignable to type \"List[_LGBM_ScikitValidSet] | None\"\n Type \"list[tuple[DataFrame, DataFrame]]\" is not assignable to type \"List[_LGBM_ScikitValidSet] | None\"\n \"list[tuple[DataFrame, DataFrame]]\" is not assignable to \"List[_LGBM_ScikitValidSet]\"\n Type parameter \"_T@list\" is invariant, but \"tuple[DataFrame, DataFrame]\" is not the same as \"_LGBM_ScikitValidSet\"\n Consider switching from \"list\" to \"Sequence\" which is covariant\n \"list[tuple[DataFrame, DataFrame]]\" is not assignable to \"None\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 21,
- "startLine": 4997
+ "startLine": 5012
},
{
"endCharacter": 43,
- "endLine": 4998,
+ "endLine": 5013,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"list[NDArray[floating[Any]]] | None\" cannot be assigned to parameter \"eval_sample_weight\" of type \"List[_LGBM_WeightType] | None\" in function \"fit\"\n Type \"list[NDArray[floating[Any]]] | None\" is not assignable to type \"List[_LGBM_WeightType] | None\"\n Type \"list[NDArray[floating[Any]]]\" is not assignable to type \"List[_LGBM_WeightType] | None\"\n \"list[NDArray[floating[Any]]]\" is not assignable to \"List[_LGBM_WeightType]\"\n Type parameter \"_T@list\" is invariant, but \"NDArray[floating[Any]]\" is not the same as \"_LGBM_WeightType\"\n Consider switching from \"list\" to \"Sequence\" which is covariant\n \"list[NDArray[floating[Any]]]\" is not assignable to \"None\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 31,
- "startLine": 4998
+ "startLine": 5013
},
{
"endCharacter": 62,
- "endLine": 5001,
+ "endLine": 5016,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"list[RegressorCallback] | None\" cannot be assigned to parameter \"callbacks\" of type \"List[(...) -> Unknown] | None\" in function \"fit\"\n Type \"list[RegressorCallback] | None\" is not assignable to type \"List[(...) -> Unknown] | None\"\n Type \"list[RegressorCallback]\" is not assignable to type \"List[(...) -> Unknown] | None\"\n \"list[RegressorCallback]\" is not assignable to \"List[(...) -> Unknown]\"\n Type parameter \"_T@list\" is invariant, but \"RegressorCallback\" is not the same as \"(...) -> Unknown\"\n Consider switching from \"list\" to \"Sequence\" which is covariant\n \"list[RegressorCallback]\" is not assignable to \"None\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 22,
- "startLine": 5001
+ "startLine": 5016
},
{
"endCharacter": 35,
- "endLine": 5023,
+ "endLine": 5038,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Object of type \"None\" is not subscriptable",
"rule": "reportOptionalSubscript",
"severity": "error",
"startCharacter": 27,
- "startLine": 5023
+ "startLine": 5038
},
{
"endCharacter": 35,
- "endLine": 5069,
+ "endLine": 5084,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Object of type \"None\" is not subscriptable",
"rule": "reportOptionalSubscript",
"severity": "error",
"startCharacter": 27,
- "startLine": 5069
+ "startLine": 5084
},
{
"endCharacter": 49,
- "endLine": 5139,
+ "endLine": 5154,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Argument of type \"CatBoostPruningCallback\" cannot be assigned to parameter \"object\" of type \"RegressorCallback\" in function \"append\"\n Type \"CatBoostPruningCallback\" is not assignable to type \"RegressorCallback\"\n Type \"CatBoostPruningCallback\" is not assignable to type \"(...) -> Any\"\n \"CatBoostPruningCallback\" is not assignable to \"TrainingCallback\"",
"rule": "reportArgumentType",
"severity": "error",
"startCharacter": 33,
- "startLine": 5139
+ "startLine": 5154
},
{
"endCharacter": 75,
- "endLine": 5382,
+ "endLine": 5397,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Operator \"<=\" not supported for \"None\"",
"rule": "reportOptionalOperand",
"severity": "error",
"startCharacter": 54,
- "startLine": 5382
+ "startLine": 5397
},
{
"endCharacter": 23,
- "endLine": 5545,
+ "endLine": 5560,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"best_params\" is possibly unbound",
"rule": "reportPossiblyUnboundVariable",
"severity": "error",
"startCharacter": 12,
- "startLine": 5545
+ "startLine": 5560
},
{
"endCharacter": 38,
- "endLine": 5552,
+ "endLine": 5567,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"best_params\" is possibly unbound",
"rule": "reportPossiblyUnboundVariable",
"severity": "error",
"startCharacter": 27,
- "startLine": 5552
+ "startLine": 5567
},
{
"endCharacter": 22,
- "endLine": 5564,
+ "endLine": 5579,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "\"best_params\" is possibly unbound",
"rule": "reportPossiblyUnboundVariable",
"severity": "error",
"startCharacter": 11,
- "startLine": 5564
+ "startLine": 5579
},
{
"endCharacter": 22,
- "endLine": 5722,
+ "endLine": 5737,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 5722
+ "startLine": 5737
},
{
"endCharacter": 14,
- "endLine": 5758,
+ "endLine": 5773,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"params\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 5758
+ "startLine": 5773
},
{
"endCharacter": 22,
- "endLine": 5842,
+ "endLine": 5857,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 5842
+ "startLine": 5857
},
{
"endCharacter": 14,
- "endLine": 5876,
+ "endLine": 5891,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"params\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 5876
+ "startLine": 5891
},
{
"endCharacter": 22,
- "endLine": 5947,
+ "endLine": 5962,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 5947
+ "startLine": 5962
},
{
"endCharacter": 22,
- "endLine": 6048,
+ "endLine": 6063,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 8,
- "startLine": 6048
+ "startLine": 6063
},
{
"endCharacter": 26,
- "endLine": 6131,
+ "endLine": 6146,
"file": "quickadapter/user_data/strategies/Utils.py",
"message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
"rule": "reportRedeclaration",
"severity": "error",
"startCharacter": 12,
- "startLine": 6131
+ "startLine": 6146
}
],
"filesAnalyzed": 5,
4. Open trades use the custom volatility-based stoploss, which never loosens,
including after partial exits. The strategy stoploss is -2.5%; leverage,
execution and exchange conditions affect the actual outcome.
-5. Three take-profit stages request 40%, 30% and 20% of the stake remaining at
- each stage. Exchange minimums can turn a partial request into a full close.
- The final target arms a persisted trailing full exit: a material adverse
- retracement exits, not elapsed stagnation alone. Open orders block new staged
- adjustments.
+5. The exit ladder targets equal shares of the initial stake: nominally 1/N
+ per rung, or 25% with the four default stages. Partial rungs request
+ `1 / (N - k)` of the remaining stake at zero-based stage `k`; the final
+ exit closes the remainder. Adding or removing a rung in `exit_stages`
+ changes the nominal shares. Exchange lot precision, minimum-stake limits
+ and canceled partially filled orders can change the realized shares;
+ minimums can reduce a partial request or turn it into a full close.
+ An executable partial lot is preserved through stake conversion; if no
+ callback stake reproduces the selected lot, the strategy requests a full close.
+ The last rung's target arms a persisted trailing full exit: a material
+ adverse retracement exits, not elapsed stagnation alone. Open orders
+ block new staged adjustments.
6. Model expiration (`do_predict=2`) requests an exit. A valid opposite extrema
signal requests an exit only after price-reversal confirmation. Outlier
predictions are counted per candle; that count is not itself an unconditional
### Exit pricing
-| Path | Runtime fallback | Type / Range | Description |
-| -------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| exit_pricing.trade_natr_method | `moving_average` | enum {`moving_average`,`quantile_interpolation`,`weighted_average`} | Trade NATR (Normalized Average True Range) aggregation for stoploss and take-profit distances. `moving_average` uses KAMA to preserve nonnegative volatility. The stoploss never loosens, including after partial exits, and remains unchanged on order fills. |
-| exit_pricing.final_take_profit_retracement_fraction | 0.5 | float (0,1] | Fraction of the final take-profit target distance used as the frozen trailing retracement distance after the final target arms the exit. The final exit tracks the best subsequent per-candle rate and exits only after this material adverse move; elapsed stagnation alone does not exit. Plot annotations show only the current trail boundary from the candle that established it; earlier boundaries are not retained. |
-| exit_pricing.take_profit_stage_natr_multiplier_fraction_series | `fibonacci_extensions` | enum {`fibonacci_extensions`,`pi_extensions`} | Partial target distances from entry, as percentages of the full target distance: approximately 23.6%, 38.2% and 61.8% for `fibonacci_extensions`, or 3.2%, 10.1% and 31.8% for `pi_extensions`. Pi places partial targets closer to entry. Stake reduction percentages and the final target are unchanged. Invalid values use the default. |
+| Path | Runtime fallback | Type / Range | Description |
+| -------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| exit_pricing.trade_natr_method | `moving_average` | enum {`moving_average`,`quantile_interpolation`,`weighted_average`} | Trade NATR (Normalized Average True Range) aggregation for stoploss and take-profit distances. `moving_average` uses KAMA to preserve nonnegative volatility. The stoploss never loosens, including after partial exits, and remains unchanged on order fills. |
+| exit_pricing.final_take_profit_retracement_fraction | 0.5 | float (0,1] | Fraction of the final take-profit target distance used as the frozen trailing retracement distance after the final target arms the exit. The final exit tracks the best subsequent per-candle rate and exits only after this material adverse move; elapsed stagnation alone does not exit. Plot annotations show only the current trail boundary from the candle that established it; earlier boundaries are not retained. |
+| exit_pricing.take_profit_stage_natr_multiplier_fraction_series | `fibonacci_extensions` | enum {`fibonacci_extensions`,`pi_extensions`} | With the default four rungs, partial target distances are approximately 23.6%, 38.2% and 61.8% of the full target distance for `fibonacci_extensions`, or 3.2%, 10.1% and 31.8% for `pi_extensions`. Pi places partial targets closer to entry. Partial fractions are recomputed when the rung count changes; the final rung always uses the full distance. This setting changes target distances only, not nominal stake shares; execution constraints are described in the decision cycle. Invalid values use the default. |
### Reversal confirmation
from QuickAdapterV3 import QuickAdapterV3
from Utils import (
TAKE_PROFIT_STAGE_NATR_MULTIPLIER_FRACTION_SERIES,
+ get_exit_stage_stake_fractions,
get_take_profit_stage_natr_multiplier_fractions,
)
long_trade = trade()
# One candle of duration, a two-value trade NATR window and multiplier 3.0 make the
# distance open_rate * 0.07 * 3.0 * fraction * log10(10), and log10(10) is exactly 1.
- for stage in sorted(QuickAdapterV3.partial_exit_stages):
+ fractions = model.exit_stage_natr_multiplier_fractions
+ self.assertEqual(sorted(fractions), sorted(QuickAdapterV3.exit_stages))
+ for stage, fraction in fractions.items():
with self.subTest(stage=stage):
- fraction = model.partial_exit_stage_natr_multiplier_fractions[stage]
self.assertIsInstance(fraction, float)
self.assertGreater(fraction, 0.0)
- self.assertLess(fraction, 1.0)
distance = 100.0 * 0.07 * MULTIPLIER * fraction
target = model.get_take_profit_target(frame, long_trade, stage)
self.assertIsNotNone(target)
assert_allclose(target[0], 100.0 + distance, rtol=1e-9, atol=1e-9)
assert_allclose(target[1], distance, rtol=1e-9, atol=1e-9)
- for stage in (QuickAdapterV3._FINAL_EXIT_STAGE, 99, -1):
- with self.subTest(final_stage=stage):
- target = model.get_take_profit_target(frame, long_trade, stage)
- assert_allclose(
- target[0],
- 100.0 * (1 + 0.07 * MULTIPLIER * QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[0]),
- rtol=1e-9,
- atol=1e-9,
- )
- stages = [
- model.get_take_profit_target(frame, long_trade, stage)[1]
- for stage in (0, 1, 2, QuickAdapterV3._FINAL_EXIT_STAGE)
- ]
- self.assertEqual(stages, sorted(stages))
-
- def test_the_fibonacci_extensions_define_the_default_partial_ladder(self):
+ # Partial rungs stay inside the full distance; only the final one reaches it.
+ for stage in sorted(QuickAdapterV3.exit_stages):
+ if stage != QuickAdapterV3.final_exit_stage():
+ self.assertLess(fractions[stage], 1.0)
+ self.assertEqual(fractions[QuickAdapterV3.final_exit_stage()], 1.0)
+ # A stage the ladder does not define is priced at the full distance.
+ self.assertEqual(model.get_exit_stage_natr_multiplier_fraction(99), 1.0)
+ self.assertEqual(model.get_exit_stage_natr_multiplier_fraction(-1), 1.0)
+
+ def test_the_fibonacci_extensions_define_the_default_ladder(self):
# Frozen reference rungs, not a restatement of the formula: a change of
- # base or of the stage count must fail here. They are phi**-3, phi**-2
- # and phi**-1 rounded to six decimals.
+ # base or of the stage count must fail here. Three partial rungs are
+ # phi**-3, phi**-2 and phi**-1, then the full distance.
assert_allclose(
- tuple(strategy().partial_exit_stage_natr_multiplier_fractions.values()),
- (0.236068, 0.381966, 0.618034),
+ tuple(strategy().exit_stage_natr_multiplier_fractions.values()),
+ (0.236068, 0.381966, 0.618034, 1.0),
rtol=1e-6,
)
- self.assertEqual(strategy().get_exit_stage_natr_multiplier_fraction(99), 1.0)
def test_every_series_raises_its_fraction_with_the_stage_index(self):
for series in TAKE_PROFIT_STAGE_NATR_MULTIPLIER_FRACTION_SERIES:
with self.subTest(series=series):
# Stage fractions follow stage indices, not insertion order.
- reordered_stages = dict(
- sorted(QuickAdapterV3.partial_exit_stages.items(), reverse=True)
- )
- with mock.patch.object(QuickAdapterV3, "partial_exit_stages", reordered_stages):
+ reordered_stages = dict(sorted(QuickAdapterV3.exit_stages.items(), reverse=True))
+ with mock.patch.object(QuickAdapterV3, "exit_stages", reordered_stages):
model = strategy(fraction_series=series)
- by_stage = model.partial_exit_stage_natr_multiplier_fractions
- stages = sorted(QuickAdapterV3.partial_exit_stages)
+ by_stage = model.exit_stage_natr_multiplier_fractions
+ stages = sorted(QuickAdapterV3.exit_stages)
self.assertEqual(sorted(by_stage), stages)
for earlier, later in pairwise(stages):
- self.assertLess(by_stage[earlier], by_stage[later])
+ self.assertLessEqual(by_stage[earlier], by_stage[later])
- def test_no_series_ladder_reaches_the_final_stage_fraction(self):
+ def test_no_series_ladder_reaches_the_final_stage_fraction_early(self):
for series in TAKE_PROFIT_STAGE_NATR_MULTIPLIER_FRACTION_SERIES:
with self.subTest(series=series):
fractions = tuple(
- strategy(
- fraction_series=series
- ).partial_exit_stage_natr_multiplier_fractions.values()
+ strategy(fraction_series=series).exit_stage_natr_multiplier_fractions.values()
)
- self.assertNotIn(1.0, fractions)
- self.assertEqual(max(fractions), fractions[-1])
+ # Only the last rung carries the full distance.
+ self.assertEqual(fractions[-1], 1.0)
+ self.assertNotIn(1.0, fractions[:-1])
def test_the_ladder_is_indexed_by_the_stage_count(self):
self.assertEqual(
self.assertEqual(len(fractions), count)
self.assertEqual(max(fractions), fractions[-1])
- def test_the_pi_extensions_define_the_partial_ladder(self):
+ def test_the_pi_extensions_define_the_ladder(self):
assert_allclose(
tuple(
strategy(
fraction_series="pi_extensions"
- ).partial_exit_stage_natr_multiplier_fractions.values()
+ ).exit_stage_natr_multiplier_fractions.values()
),
- (0.03225153, 0.10132118, 0.31830989),
+ (0.03225153, 0.10132118, 0.31830989, 1.0),
rtol=1e-6,
)
fibonacci = strategy(fraction_series="fibonacci_extensions")
pi = strategy(fraction_series="pi_extensions")
self.assertEqual(pi.take_profit_stage_natr_multiplier_fraction_series, "pi_extensions")
- for stage in sorted(QuickAdapterV3.partial_exit_stages):
+ partial_stages = list(QuickAdapterV3.partial_exit_stages())
+ for stage in partial_stages:
with self.subTest(stage=stage):
fibonacci_distance = fibonacci.get_take_profit_target(frame, long_trade, stage)[1]
pi_distance = pi.get_take_profit_target(frame, long_trade, stage)[1]
self.assertLess(pi_distance, fibonacci_distance)
# The final distance is independent of the partial extension series.
self.assertEqual(
- fibonacci.get_take_profit_target(frame, long_trade, QuickAdapterV3._FINAL_EXIT_STAGE),
- pi.get_take_profit_target(frame, long_trade, QuickAdapterV3._FINAL_EXIT_STAGE),
+ fibonacci.get_take_profit_target(frame, long_trade, QuickAdapterV3.final_exit_stage()),
+ pi.get_take_profit_target(frame, long_trade, QuickAdapterV3.final_exit_stage()),
)
def test_fraction_series_validates_names_and_stage_counts(self):
with self.assertRaises(ValueError):
get_take_profit_stage_natr_multiplier_fractions("fibonacci_extensions", -1)
+ def test_the_remaining_stake_share_grows_with_the_stage_index(self):
+ # Shares apply to the stake still open, so each rung closes a larger
+ # fraction of a smaller remainder than the one before it, and the last
+ # rung closes everything that is left.
+ assert_allclose(get_exit_stage_stake_fractions(4), (0.25, 1 / 3, 0.5, 1.0), rtol=1e-15)
+ for count in (1, 2, 3, 4, 5, 8):
+ with self.subTest(stage_count=count):
+ fractions = get_exit_stage_stake_fractions(count)
+ self.assertEqual(len(fractions), count)
+ for earlier, later in pairwise(fractions):
+ self.assertLess(earlier, later)
+ self.assertEqual(fractions[-1], 1.0)
+
+ def test_a_ladder_without_any_stage_is_rejected(self):
+ for invalid in (0, -1):
+ with self.subTest(stage_count=invalid), self.assertRaises(ValueError):
+ get_exit_stage_stake_fractions(invalid)
+
+ def test_only_the_last_stage_share_closes_the_whole_position(self):
+ # Every earlier rung must leave something behind.
+ for count in (1, 2, 3, 4, 5, 8):
+ with self.subTest(stage_count=count):
+ fractions = get_exit_stage_stake_fractions(count)
+ remaining = 1.0
+ for fraction in fractions:
+ self.assertGreater(fraction, 0.0)
+ remaining *= 1.0 - fraction
+ self.assertAlmostEqual(remaining, 0.0, places=12)
+
+ def test_the_stake_shares_follow_the_configured_stage_count(self):
+ # Adding or removing a rung re-sizes every share without any literal.
+ for count in (1, 2, 4):
+ with self.subTest(stage_count=count):
+ stages = dict.fromkeys(range(count), "lime")
+ with mock.patch.object(QuickAdapterV3, "exit_stages", stages):
+ model = strategy()
+ self.assertEqual(
+ model.exit_stage_stake_fractions,
+ dict(zip(range(count), get_exit_stage_stake_fractions(count), strict=True)),
+ )
+
def test_a_short_take_profit_target_flips_the_sign(self):
model = strategy()
frame = candles([100.0, 100.0, 100.0], natr=[1.0, 4.0, 8.0], multiplier=MULTIPLIER)
underwater = model.get_take_profit_target(
candles([100.0, 100.0, 100.0], natr=[1.0, 400.0, 800.0], multiplier=MULTIPLIER),
trade(open_rate=1e-9, is_short=True),
- QuickAdapterV3._FINAL_EXIT_STAGE,
+ QuickAdapterV3.final_exit_stage(),
)
self.assertIsNone(underwater)
import datetime
import math
import unittest
-from types import SimpleNamespace
+from types import MethodType, SimpleNamespace
from unittest import mock
import numpy as np
import pandas as pd
-from freqtrade.enums import RunMode
+from ccxt import DECIMAL_PLACES, SIGNIFICANT_DIGITS, TICK_SIZE
+from freqtrade.enums import RunMode, TradingMode
+from freqtrade.exchange import Exchange
+from freqtrade.exchange.exchange_utils import amount_to_contract_precision, contracts_to_amount
+from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Order, Trade
from qa_support import PAIR, QaTestCase, model_config, temporary_directory
from QuickAdapterV3 import QuickAdapterV3
0.2,
0.2,
)
- stake_reduction = -100.0 * QuickAdapterV3.partial_exit_stages[0][0]
+ # Four exits release the position in equal shares, so the
+ # first one closes a quarter of the 100 stake.
+ stake_reduction = -25.0
direction = "short" if short else "long"
self.assertEqual(after, (stake_reduction, f"take_profit_{direction}_0"))
+ def _filled_order(self, position, amount, rate, tag=None):
+ return Order(
+ order_id=str(len(position.orders)),
+ ft_pair=PAIR,
+ ft_order_side=position.entry_side if tag is None else position.exit_side,
+ ft_is_open=False,
+ status="closed",
+ filled=amount,
+ amount=amount,
+ price=rate,
+ average=rate,
+ cost=amount * rate,
+ order_date=self.now - datetime.timedelta(minutes=5),
+ order_filled_date=self.now,
+ ft_order_tag=tag,
+ )
+
+ def _filled_position(
+ self,
+ short=False,
+ leverage=2.0,
+ amount=2.0,
+ open_rate=123.4,
+ lot=0.01,
+ contract_size=1.0,
+ precision_mode=TICK_SIZE,
+ ):
+ position = Trade(
+ pair=PAIR,
+ open_rate=open_rate,
+ open_date=self.now - datetime.timedelta(minutes=5),
+ is_short=short,
+ stake_amount=amount * open_rate / leverage,
+ amount=amount,
+ leverage=leverage,
+ exchange="binance",
+ fee_open=0.0,
+ fee_close=0.0,
+ amount_precision=lot,
+ precision_mode=precision_mode,
+ contract_size=contract_size,
+ orders=[],
+ )
+ position.orders.append(self._filled_order(position, amount, open_rate))
+ position.recalc_trade_from_orders()
+ self.custom_data(position)
+ return position
+
+ def _native_partial_exit(self, position, rate, min_cost=1.0, min_amount=None):
+ # Only market data, wallet availability and order submission are isolated.
+ exchange = SimpleNamespace(
+ markets={
+ PAIR: {
+ "contractSize": position.contract_size,
+ "limits": {
+ "cost": {"min": min_cost, "max": None},
+ "amount": {"min": min_amount, "max": None},
+ },
+ }
+ },
+ _config={},
+ trading_mode=TradingMode.FUTURES,
+ _get_max_notional_from_tiers=lambda pair, leverage: None,
+ get_rates=lambda *args: (rate, rate),
+ amount_to_contract_precision=lambda pair, amount: amount_to_contract_precision(
+ amount, position.amount_precision, position.precision_mode, position.contract_size
+ ),
+ )
+ for name in (
+ "get_contract_size",
+ "_contracts_to_amount",
+ "_get_stake_amount_limit",
+ "_get_stake_amount_considering_leverage",
+ "get_min_pair_stake_amount",
+ "get_max_pair_stake_amount",
+ ):
+ setattr(exchange, name, MethodType(getattr(Exchange, name), exchange))
+ self.model.dp._exchange = exchange
+ bot = object.__new__(FreqtradeBot)
+ bot.strategy = self.model
+ bot.exchange = exchange
+ bot.wallets = SimpleNamespace(get_available_stake_amount=lambda: 1000.0)
+ fills = []
+
+ def fill(trade, price, *, sub_trade_amt, exit_tag, **kwargs):
+ fills.append(sub_trade_amt)
+ trade.orders.append(self._filled_order(trade, sub_trade_amt, price, exit_tag))
+ trade.recalc_trade_from_orders()
+
+ bot.execute_trade_exit = fill
+ bot.check_and_call_adjust_trade_position(position)
+ return fills
+
+ def test_native_fills_preserve_non_idempotent_contract_quantities(self):
+ for precision_mode, precision in (
+ (TICK_SIZE, 1),
+ (DECIMAL_PLACES, 0),
+ (SIGNIFICANT_DIGITS, 2),
+ ):
+ for short in (False, True):
+ with self.subTest(precision_mode=precision_mode, short=short):
+ position = self._filled_position(
+ short=short,
+ amount=contracts_to_amount(110, 1 / 3),
+ open_rate=100.0,
+ lot=precision,
+ contract_size=1 / 3,
+ precision_mode=precision_mode,
+ )
+ target = self.model.get_take_profit_target(self.frame, position, 0)[0]
+ rate = target * (0.9 if short else 1.1)
+ self.assertEqual(
+ self._native_partial_exit(position, rate, min_cost=None, min_amount=1),
+ [8.999999999999998],
+ )
+ self.assertEqual(position.amount, 27.666666666666664)
+ self.assertAlmostEqual(position.stake_amount, 1383.3333333333333)
+ self.assertEqual(position.open_rate, 100.0)
+
+ def test_native_roundtrip_adjusts_up_and_down_to_preserve_the_selected_lot(self):
+ cases = (
+ (
+ "up",
+ {"amount": 2.0, "open_rate": 123.4, "lot": 0.01},
+ 0.5,
+ 1.5,
+ 61.7,
+ ),
+ (
+ "down",
+ {
+ "amount": contracts_to_amount(0.38, 1 / 3),
+ "open_rate": 100.0,
+ "lot": 7,
+ "contract_size": 1 / 3,
+ "precision_mode": DECIMAL_PLACES,
+ },
+ 0.03166663333333333,
+ 0.09500003333333332,
+ 3.166667777777777,
+ ),
+ )
+ for direction, inputs, filled_amount, remaining_amount, remaining_stake in cases:
+ for short in (False, True):
+ with self.subTest(direction=direction, short=short):
+ position = self._filled_position(short=short, leverage=3.0, **inputs)
+ target = self.model.get_take_profit_target(self.frame, position, 0)[0]
+ rate = target * (0.9 if short else 1.1)
+ self.assertEqual(
+ self._native_partial_exit(position, rate, min_cost=None, min_amount=1e-7),
+ [filled_amount],
+ )
+ self.assertEqual(position.amount, remaining_amount)
+ self.assertAlmostEqual(position.stake_amount, remaining_stake)
+ self.assertEqual(position.open_rate, inputs["open_rate"])
+
+ def test_native_minimum_clamp_preserves_a_representable_fractional_contract(self):
+ original_model = self.model
+ self.addCleanup(setattr, self, "model", original_model)
+ with mock.patch.object(QuickAdapterV3, "exit_stages", {0: "lime", 1: "yellow"}):
+ self.model = QuickAdapterV3(original_model.config)
+ self.model.freqai_info = original_model.config["freqai"]
+ self.model.bot_start()
+ self.model.dp = original_model.dp
+ for short in (False, True):
+ with self.subTest(short=short):
+ position = self._filled_position(
+ short=short,
+ leverage=1.0,
+ amount=2.01e-18,
+ open_rate=1e18,
+ lot=1,
+ contract_size=3e-20,
+ )
+ rate, min_cost = (1e17, 3.126e18) if short else (1e19, 3.126e20)
+ self.assertEqual(
+ self._native_partial_exit(position, rate, min_cost=min_cost), [9.9e-19]
+ )
+ self.assertEqual(position.amount, 1.02e-18)
+ self.assertEqual(position.stake_amount, 1.02)
+
+ def test_native_unrepresentable_selected_lots_request_the_full_quantity(self):
+ cases = (
+ (
+ "native-quantity-grid",
+ 2,
+ {"amount": 2e-18, "open_rate": 1e18, "lot": 1, "contract_size": 1e-20},
+ 1e19,
+ 9.329e20,
+ ),
+ (
+ "callback-float-grid",
+ 8,
+ {
+ "amount": 61063600.9973608,
+ "open_rate": 0.000736753283349331,
+ "lot": 9,
+ "precision_mode": DECIMAL_PLACES,
+ },
+ None,
+ 0.0,
+ ),
+ )
+ original_model = self.model
+ self.addCleanup(setattr, self, "model", original_model)
+ for name, stage_count, inputs, rate, min_cost in cases:
+ with (
+ self.subTest(name=name),
+ mock.patch.object(
+ QuickAdapterV3, "exit_stages", dict.fromkeys(range(stage_count), "lime")
+ ),
+ ):
+ self.model = QuickAdapterV3(original_model.config)
+ self.model.freqai_info = original_model.config["freqai"]
+ self.model.bot_start()
+ self.model.dp = original_model.dp
+ position = self._filled_position(leverage=1.0, **inputs)
+ if rate is None:
+ rate = self.model.get_take_profit_target(self.frame, position, 0)[0] * 1.1
+ self.assertEqual(
+ self._native_partial_exit(position, rate, min_cost=min_cost),
+ [inputs["amount"]],
+ )
+
+ def test_native_fills_release_equal_lots_and_leave_one_share_for_the_final_exit(self):
+ original_model = self.model
+ self.addCleanup(setattr, self, "model", original_model)
+ for stage_count in (2, 3, 4, 5):
+ with mock.patch.object(
+ QuickAdapterV3, "exit_stages", dict.fromkeys(range(stage_count), "lime")
+ ):
+ self.model = QuickAdapterV3(original_model.config)
+ self.model.freqai_info = original_model.config["freqai"]
+ self.model.bot_start()
+ self.model.dp = original_model.dp
+ for leverage in (1.0, 2.0, 5.0):
+ for short in (False, True):
+ with self.subTest(stage_count=stage_count, leverage=leverage, short=short):
+ position = self._filled_position(
+ short, leverage, amount=0.5 * stage_count
+ )
+ initial_stake = position.stake_amount
+ for stage in range(stage_count - 1):
+ target = self.model.get_take_profit_target(
+ self.frame, position, stage
+ )[0]
+ rate = target + (-1.0 if short else 1.0)
+ before = position.stake_amount
+ self.assertEqual(self._native_partial_exit(position, rate), [0.5])
+ self.assertAlmostEqual(
+ before - position.stake_amount, initial_stake / stage_count
+ )
+ self.assertEqual(position.amount, 0.5)
+ self.assertAlmostEqual(
+ position.stake_amount, initial_stake / stage_count
+ )
+ self.assertEqual(self._native_partial_exit(position, rate), [])
+
+ def test_native_minimum_does_not_turn_a_representable_share_into_a_full_close(self):
+ for leverage in (1.0, 2.0, 5.0):
+ with self.subTest(leverage=leverage):
+ position = self._filled_position(leverage=leverage)
+ self.assertEqual(self._native_partial_exit(position, 135.74), [0.5])
+ # 64 with the native 5% reserve needs 67.2 quote; 0.50 meets it, 0.49 does not.
+ self.assertEqual(self._native_partial_exit(position, 135.74, min_cost=64.0), [0.5])
+ self.assertEqual(position.amount, 1.0)
+
+ def test_native_minimum_can_still_clamp_a_share_to_preserve_the_remainder(self):
+ position = self._filled_position()
+ for _ in range(2):
+ self.assertEqual(self._native_partial_exit(position, 135.74), [0.5])
+ self.assertEqual(self._native_partial_exit(position, 150.0, min_cost=73.1 / 1.05), [0.49])
+ exchange = self.model.dp._exchange
+ exit_min = exchange.get_min_pair_stake_amount(PAIR, 150.0, 0.0, position.leverage)
+ remaining_min = exchange.get_min_pair_stake_amount(
+ PAIR, 150.0, self.model.stoploss, position.leverage
+ ) * (1.0 + QuickAdapterV3._PARTIAL_EXIT_MIN_STAKE_MARGIN)
+ self.assertGreaterEqual(0.49 * 150.0, exit_min * position.leverage)
+ self.assertGreaterEqual(position.amount * 150.0, remaining_min * position.leverage)
+
+ def test_native_stake_conversion_keeps_a_lot_with_a_sub_decimal_quantum_stake(self):
+ position = self._filled_position(leverage=10.0, amount=0.02, open_rate=1e-16, lot=0.001)
+ self.assertEqual(self._native_partial_exit(position, 1.0, min_cost=0.0), [0.005])
+ self.assertEqual(position.amount, 0.015)
+
+ def test_native_quantity_ceiling_preserves_a_representable_fractional_contract(self):
+ with mock.patch.object(QuickAdapterV3, "exit_stages", {0: "lime", 1: "yellow"}):
+ position = self._filled_position(
+ leverage=1.0, amount=2.7e-18, open_rate=1e18, lot=1, contract_size=3e-19
+ )
+ self.assertEqual(self._native_partial_exit(position, 1e19, min_cost=0.0), [9e-19])
+ self.assertEqual(position.amount, 1.8e-18)
+
def test_expired_models_exit_before_order_stage_and_date_guards(self):
self.frame.loc[self.frame.index[-1], "date"] = pd.NaT
self.frame["do_predict"] = 2
https://github.com/sponsors/robcaulk
"""
- version = "3.13.0-rc.14"
+ version = "3.13.0-rc.15"
_CALIBRATION_START_KEY: Final[str] = "quickadapter_calibration_start"
_DEPLOYMENT_COORDINATE_MARKER_KEY: Final[str] = "quickadapter_deployment_coordinates"
get_custom_protections_config,
get_distance,
get_exit_pricing_config,
+ get_exit_stage_stake_fractions,
get_fit_live_predictions_candles,
get_label_defaults,
get_label_horizon_candles,
_ANNOTATION_LINE_OFFSET_CANDLES: Final[int] = 10
def version(self) -> str:
- return "3.13.0-rc.14"
+ return "3.13.0-rc.15"
timeframe = "5m"
timeframe_minutes = timeframe_to_minutes(timeframe)
position_adjustment_enable = True
- # {stage: (stake_percent, color)}. The reciprocal-extension fractions are
- # not literals here: they resolve from the configured
- # ``exit_pricing.take_profit_stage_natr_multiplier_fraction_series`` ladder,
- # which is their single source of truth. The final rung stays the literal.
- partial_exit_stages: ClassVar[dict[int, tuple[float, str]]] = {
- 0: (0.4, "lime"),
- 1: (0.3, "yellow"),
- 2: (0.2, "coral"),
+ # {stage: color} for the whole exit ladder, the final full exit included.
+ # The entry count is the single source of truth for the ladder: distances,
+ # stake shares and the final rung all derive from it. Adding or removing a
+ # rung is the only edit needed.
+ exit_stages: ClassVar[dict[int, str]] = {
+ 0: "lime",
+ 1: "yellow",
+ 2: "coral",
+ 3: "deepskyblue",
}
- # (natr_multiplier_fraction, stake_percent, color)
- _FINAL_EXIT_STAGE_PARAMS: Final[tuple[float, float, str]] = (
- 1.0,
- 1.0,
- "deepskyblue",
- )
-
- # Final full-exit stage, derived from the configured partial exits.
- _FINAL_EXIT_STAGE: Final[int] = max(partial_exit_stages.keys(), default=-1) + 1
-
# ``get_trade_exit_stage`` derives a stage from the number of filled take-profit
# exits, so every stage it can reach must exist here. A gap would price a
# missing stage at the final rung instead of arming it.
- assert sorted(partial_exit_stages) == list(range(len(partial_exit_stages)))
+ assert sorted(exit_stages) == list(range(len(exit_stages)))
_TAKE_PROFIT_ORDER_TAG_PREFIX: Final[str] = "take_profit_"
_FINAL_TAKE_PROFIT_STATE_KEY: Final[str] = "final_take_profit_state"
return str(self.exit_pricing["take_profit_stage_natr_multiplier_fraction_series"])
@cached_property
- def partial_exit_stage_natr_multiplier_fractions(self) -> dict[int, float]:
- """Reciprocal-extension fractions of the full take-profit distance, by stage."""
+ def exit_stage_natr_multiplier_fractions(self) -> dict[int, float]:
+ """Target distance of each stage as a fraction of the full distance.
+
+ Partial rungs follow the configured reciprocal-extension series; the
+ final rung sits at the full distance.
+ """
+ partial_stages = QuickAdapterV3.partial_exit_stages()
fractions = get_take_profit_stage_natr_multiplier_fractions(
self.take_profit_stage_natr_multiplier_fraction_series,
- len(QuickAdapterV3.partial_exit_stages),
+ len(partial_stages),
)
- return dict(zip(sorted(QuickAdapterV3.partial_exit_stages), fractions, strict=True))
+ ladder = dict(zip(partial_stages, fractions, strict=True))
+ ladder[QuickAdapterV3.final_exit_stage()] = 1.0
+ return ladder
+
+ @cached_property
+ def exit_stage_stake_fractions(self) -> dict[int, float]:
+ """Nominal share of the stake still open that each stage requests.
+
+ With ``n`` stages, stage ``k`` requests ``1 / (n - k)`` of the remaining
+ stake: nominally ``1 / n`` of the initial stake with complete fills and
+ no exchange sizing adjustments. The last stage closes the remainder.
+ """
+ fractions = get_exit_stage_stake_fractions(len(QuickAdapterV3.exit_stages))
+ return dict(zip(sorted(QuickAdapterV3.exit_stages), fractions, strict=True))
def get_exit_stage_natr_multiplier_fraction(self, exit_stage: int) -> float:
- """Return a partial reciprocal-extension fraction or the final fraction ``1.0``."""
- fractions = self.partial_exit_stage_natr_multiplier_fractions
- if exit_stage in fractions:
- return fractions[exit_stage]
- return QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[0]
+ """Return the stage's distance fraction, or the full distance if unknown."""
+ return self.exit_stage_natr_multiplier_fractions.get(exit_stage, 1.0)
+
+ @staticmethod
+ def partial_exit_stages() -> tuple[int, ...]:
+ """Every rung but the last, which closes the remainder."""
+ return tuple(sorted(QuickAdapterV3.exit_stages)[:-1])
+
+ @staticmethod
+ def final_exit_stage() -> int:
+ """The last rung, which closes whatever the earlier ones left."""
+ return max(QuickAdapterV3.exit_stages)
+
+ @staticmethod
+ def is_partial_exit_stage(exit_stage: int) -> bool:
+ """Whether ``exit_stage`` releases one slice rather than the remainder."""
+ return exit_stage in QuickAdapterV3.partial_exit_stages()
@cached_property
def reversal_confirmation(self) -> dict[str, int | float]:
trade_natr_method = self.trade_natr_method
final_take_profit_retracement_fraction = self.final_take_profit_retracement_fraction
fraction_series = self.take_profit_stage_natr_multiplier_fraction_series
- partial_exit_stage_fractions = self.partial_exit_stage_natr_multiplier_fractions
protections = self.protections
logger.info("=" * 60)
f" natr_multiplier_fraction: {format_number(QuickAdapterV3._CUSTOM_STOPLOSS_NATR_MULTIPLIER_FRACTION)}"
)
- logger.info("Partial Take-Profit Stages:")
- for stage, (
- stake_percent,
- color,
- ) in QuickAdapterV3.partial_exit_stages.items():
+ stage_count = len(QuickAdapterV3.exit_stages)
+ distance_fractions = self.exit_stage_natr_multiplier_fractions
+ stake_fractions = self.exit_stage_stake_fractions
+ logger.info(f"Exit Stages: {stage_count} nominally equal shares of the initial stake")
+ for stage in sorted(QuickAdapterV3.exit_stages):
logger.info(
f" stage {stage}: natr_multiplier_fraction="
- f"{format_number(partial_exit_stage_fractions[stage])}, "
- f"stake_percent={format_number(stake_percent)}, color={color}"
+ f"{format_number(distance_fractions[stage])}, "
+ f"stake_fraction_of_remaining={format_number(stake_fractions[stage])}, "
+ f"stake_share_of_initial={format_number(1 / stage_count)}, "
+ f"color={QuickAdapterV3.exit_stages[stage]}"
+ + (
+ " (final, closes the remainder)"
+ if stage == QuickAdapterV3.final_exit_stage()
+ else ""
+ )
)
- logger.info("Final Exit:")
- logger.info(
- f" natr_multiplier_fraction: {format_number(QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[0])}"
- )
- logger.info(f" stake_percent: {format_number(QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[1])}")
- logger.info(f" color: {QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[2]}")
-
logger.info("Protections:")
if protections:
for protection in protections:
for order in trade.select_filled_orders(trade.exit_side)
if (order.ft_order_tag or "").startswith(QuickAdapterV3._TAKE_PROFIT_ORDER_TAG_PREFIX)
)
- return min(n_filled_take_profit_exits, QuickAdapterV3._FINAL_EXIT_STAGE)
+ return min(n_filled_take_profit_exits, QuickAdapterV3.final_exit_stage())
@staticmethod
@lru_cache(maxsize=_CACHE_MAXSIZE_LARGE)
return None
trade_exit_stage = QuickAdapterV3.get_trade_exit_stage(trade)
- if trade_exit_stage not in QuickAdapterV3.partial_exit_stages:
+ if not QuickAdapterV3.is_partial_exit_stage(trade_exit_stage):
return None
df, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.config.get("timeframe"))
),
)
if trade_partial_exit:
- trade_stake_percent = QuickAdapterV3.partial_exit_stages[trade_exit_stage][0]
- trade_partial_stake_amount = trade_stake_percent * trade.stake_amount
+ remaining_stages = len(QuickAdapterV3.exit_stages) - trade_exit_stage
tag = (
f"{QuickAdapterV3._TAKE_PROFIT_ORDER_TAG_PREFIX}"
f"{trade.trade_direction}_{trade_exit_stage}"
current_position_value = trade.amount * current_exit_rate
if current_position_value <= remaining_minimum_value:
return -trade.stake_amount, tag
- trade_partial_stake_amount = min(
- trade_partial_stake_amount,
- trade.stake_amount * (1 - remaining_minimum_value / current_position_value),
- )
- exit_amount = exchange.amount_to_contract_precision(
- pair,
- abs(
- float(
- FtPrecise(trade_partial_stake_amount)
- * FtPrecise(trade.amount)
- / FtPrecise(trade.stake_amount)
- )
- ),
+ raw_exit_amount = min(
+ float(FtPrecise(trade.amount) / FtPrecise(remaining_stages)),
+ trade.amount - remaining_minimum_value / current_exit_rate,
)
+ exit_amount = exchange.amount_to_contract_precision(pair, raw_exit_amount)
if (
exit_amount <= 0
or exit_amount * current_exit_rate < exit_minimum_value
or (trade.amount - exit_amount) * current_exit_rate < remaining_minimum_value
):
return -trade.stake_amount, tag
- return (
- -trade_partial_stake_amount,
- tag,
+ # Use a native-domain antecedent; exchange quantization need not be idempotent.
+ native_raw_exit_amount = FtPrecise(raw_exit_amount) / FtPrecise(1)
+ native_raw_exit_quantity = float(native_raw_exit_amount)
+ if (
+ native_raw_exit_quantity != raw_exit_amount
+ and exchange.amount_to_contract_precision(pair, native_raw_exit_quantity)
+ != exit_amount
+ ):
+ native_raw_exit_quantity = float(native_raw_exit_amount + FtPrecise("1e-18"))
+ if (
+ exchange.amount_to_contract_precision(pair, native_raw_exit_quantity)
+ != exit_amount
+ ):
+ return -trade.stake_amount, tag
+ trade_partial_stake_amount = (
+ native_raw_exit_quantity / trade.amount * trade.stake_amount
)
+ rounding_up = None
+ while 0.0 < trade_partial_stake_amount < trade.stake_amount:
+ roundtrip_amount = exchange.amount_to_contract_precision(
+ pair,
+ abs(
+ float(
+ FtPrecise(trade_partial_stake_amount)
+ * FtPrecise(trade.amount)
+ / FtPrecise(trade.stake_amount)
+ )
+ ),
+ )
+ if roundtrip_amount == exit_amount:
+ return -trade_partial_stake_amount, tag
+ if rounding_up is None:
+ rounding_up = roundtrip_amount < exit_amount
+ elif (roundtrip_amount < exit_amount) != rounding_up:
+ # Adjacent callback floats straddle the lot: no exact request exists.
+ break
+ trade_partial_stake_amount = math.nextafter(
+ trade_partial_stake_amount, math.inf if rounding_up else 0.0
+ )
+ return -trade.stake_amount, tag
return None
return None
trade_exit_stage = QuickAdapterV3.get_trade_exit_stage(trade)
- if trade_exit_stage in QuickAdapterV3.partial_exit_stages:
+ if QuickAdapterV3.is_partial_exit_stage(trade_exit_stage):
return None
if not has_valid_candle_date:
trade_exit_stage = QuickAdapterV3.get_trade_exit_stage(trade)
- for take_profit_stage in QuickAdapterV3.partial_exit_stages:
+ for take_profit_stage in QuickAdapterV3.partial_exit_stages():
if take_profit_stage < trade_exit_stage:
continue
"end": end_date,
"y_start": partial_take_profit_price,
"y_end": partial_take_profit_price,
- "color": QuickAdapterV3.partial_exit_stages[take_profit_stage][1],
+ "color": QuickAdapterV3.exit_stages[take_profit_stage],
"line_style": "solid",
"width": 1,
"label": f"Partial Take-Profit Stage {take_profit_stage}",
}
annotations.append(take_profit_line_annotation)
- final_exit_stage = QuickAdapterV3._FINAL_EXIT_STAGE
+ final_exit_stage = QuickAdapterV3.final_exit_stage()
raw_final_take_profit_state = trade.get_custom_data(
QuickAdapterV3._FINAL_TAKE_PROFIT_STATE_KEY
)
"end": end_date,
"y_start": final_take_profit_price,
"y_end": final_take_profit_price,
- "color": QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[2],
+ "color": QuickAdapterV3.exit_stages[
+ QuickAdapterV3.final_exit_stage()
+ ],
"line_style": "solid",
"width": 1,
"label": "Final Take-Profit Trail (current)",
"end": end_date,
"y_start": final_take_profit_price,
"y_end": final_take_profit_price,
- "color": QuickAdapterV3._FINAL_EXIT_STAGE_PARAMS[2],
+ "color": QuickAdapterV3.exit_stages[QuickAdapterV3.final_exit_stage()],
"line_style": "solid",
"width": 1,
"label": "Final Take-Profit Arming Target",
# These fractions place partial targets inside the full take-profit distance;
# they do not extend it. Fibonacci uses integer powers of phi; pi uses integer
# powers of pi as a custom geometric construction, not a trading convention.
-# The final fraction ``1.0`` is the separate ``_FINAL_EXIT_STAGE_PARAMS``
-# literal.
+# The strategy appends the final fraction ``1.0`` to the generated
+# partial-target distance ladder.
_TAKE_PROFIT_STAGE_NATR_MULTIPLIER_FRACTION_BASES: Final[dict[str, float]] = {
"fibonacci_extensions": (1.0 + math.sqrt(5.0)) / 2.0,
"pi_extensions": math.pi,
return fractions
+@lru_cache(maxsize=_CACHE_MAXSIZE_SMALL)
+def get_exit_stage_stake_fractions(stage_count: int) -> tuple[float, ...]:
+ """Return each exit's share of the stake still open at that stage.
+
+ A position split across ``stage_count`` exits releases ``1 / stage_count``
+ of its initial stake at each one. The stake remaining before stage ``k`` is
+ ``(stage_count - k) / stage_count`` of the initial one, so releasing
+ ``1 / (stage_count - k)`` of it closes exactly one share. The last stage
+ takes the whole remainder.
+ """
+ if stage_count <= 0:
+ raise ValueError(f"Invalid stage_count value {stage_count!r}: must be >= 1")
+ return tuple(1.0 / (stage_count - stage) for stage in range(stage_count))
+
+
SPARSE_TRAINING_MASS_THRESHOLD: Final[float] = 0.05
DEFAULT_FIT_LIVE_PREDICTIONS_CANDLES: Final[int] = 100