Skip to content

Commit ff1a78a

Browse files
committed
(feat) last controllers version
1 parent cd5430b commit ff1a78a

File tree

6 files changed

+82
-717
lines changed

6 files changed

+82
-717
lines changed

bots/controllers/generic/grid_strike_grid_component.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class GridStrikeConfig(ControllerConfigBase):
1717
"""
1818
Configuration required to run the GridStrike strategy for one connector and trading pair.
1919
"""
20-
controller_type: str = "generic"
20+
controller_type = "generic"
2121
controller_name: str = "grid_strike_grid_component"
2222
candles_config: List[CandlesConfig] = []
2323

bots/controllers/generic/pmm.py

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from typing import Dict, List, Optional, Set, Tuple, Union
33

44
from pydantic import Field, field_validator
5+
from pydantic_core.core_schema import ValidationInfo
56

6-
from hummingbot.client.config.config_data_types import ClientFieldData
77
from hummingbot.core.data_type.common import OrderType, PositionMode, PriceType, TradeType
88
from hummingbot.core.data_type.trade_fee import TokenAmount
99
from hummingbot.data_feed.candles_feed.data_types import CandlesConfig
@@ -137,19 +137,17 @@ class PMMConfig(ControllerConfigBase):
137137
)
138138
global_take_profit: Decimal = Decimal("0.02")
139139

140-
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
141-
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
142-
@validator("take_profit", pre=True, always=True)
140+
@field_validator("take_profit", mode="before")
141+
@classmethod
143142
def validate_target(cls, v):
144143
if isinstance(v, str):
145144
if v == "":
146145
return None
147146
return Decimal(v)
148147
return v
149148

150-
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
151-
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
152-
@validator('take_profit_order_type', pre=True, allow_reuse=True, always=True)
149+
@field_validator('take_profit_order_type', mode="before")
150+
@classmethod
153151
def validate_order_type(cls, v) -> OrderType:
154152
if isinstance(v, OrderType):
155153
return v
@@ -165,20 +163,8 @@ def validate_order_type(cls, v) -> OrderType:
165163
pass
166164
raise ValueError(f"Invalid order type: {v}. Valid options are: {', '.join(OrderType.__members__)}")
167165

168-
@property
169-
def triple_barrier_config(self) -> TripleBarrierConfig:
170-
return TripleBarrierConfig(
171-
take_profit=self.take_profit,
172-
trailing_stop=None,
173-
open_order_type=OrderType.LIMIT_MAKER, # Defaulting to LIMIT as is a Maker Controller
174-
take_profit_order_type=self.take_profit_order_type,
175-
stop_loss_order_type=OrderType.MARKET, # Defaulting to MARKET as per requirement
176-
time_limit_order_type=OrderType.MARKET # Defaulting to MARKET as per requirement
177-
)
178-
179-
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
180-
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
181-
@validator('buy_spreads', 'sell_spreads', pre=True, always=True)
166+
@field_validator('buy_spreads', 'sell_spreads', mode="before")
167+
@classmethod
182168
def parse_spreads(cls, v):
183169
if v is None:
184170
return []
@@ -188,18 +174,18 @@ def parse_spreads(cls, v):
188174
return [float(x.strip()) for x in v.split(',')]
189175
return v
190176

191-
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
192-
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
193-
@validator('buy_amounts_pct', 'sell_amounts_pct', pre=True, always=True)
194-
def parse_and_validate_amounts(cls, v, values, field):
177+
@field_validator('buy_amounts_pct', 'sell_amounts_pct', mode="before")
178+
@classmethod
179+
def parse_and_validate_amounts(cls, v, validation_info: ValidationInfo):
180+
field_name = validation_info.field_name
195181
if v is None or v == "":
196-
spread_field = field.name.replace('amounts_pct', 'spreads')
197-
return [1 for _ in values[spread_field]]
182+
spread_field = field_name.replace('amounts_pct', 'spreads')
183+
return [1 for _ in validation_info.data[spread_field]]
198184
if isinstance(v, str):
199185
return [float(x.strip()) for x in v.split(',')]
200-
elif isinstance(v, list) and len(v) != len(values[field.name.replace('amounts_pct', 'spreads')]):
186+
elif isinstance(v, list) and len(v) != len(validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
201187
raise ValueError(
202-
f"The number of {field.name} must match the number of {field.name.replace('amounts_pct', 'spreads')}.")
188+
f"The number of {field_name} must match the number of {field_name.replace('amounts_pct', 'spreads')}.")
203189
return v
204190

205191
@field_validator('position_mode', mode="before")
@@ -211,6 +197,17 @@ def validate_position_mode(cls, v) -> PositionMode:
211197
raise ValueError(f"Invalid position mode: {v}. Valid options are: {', '.join(PositionMode.__members__)}")
212198
return v
213199

200+
@property
201+
def triple_barrier_config(self) -> TripleBarrierConfig:
202+
return TripleBarrierConfig(
203+
take_profit=self.take_profit,
204+
trailing_stop=None,
205+
open_order_type=OrderType.LIMIT_MAKER, # Defaulting to LIMIT as is a Maker Controller
206+
take_profit_order_type=self.take_profit_order_type,
207+
stop_loss_order_type=OrderType.MARKET, # Defaulting to MARKET as per requirement
208+
time_limit_order_type=OrderType.MARKET # Defaulting to MARKET as per requirement
209+
)
210+
214211
def update_parameters(self, trade_type: TradeType, new_spreads: Union[List[float], str], new_amounts_pct: Optional[Union[List[int], str]] = None):
215212
spreads_field = 'buy_spreads' if trade_type == TradeType.BUY else 'sell_spreads'
216213
amounts_pct_field = 'buy_amounts_pct' if trade_type == TradeType.BUY else 'sell_amounts_pct'

bots/controllers/generic/quantum_grid_allocator.py

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
from typing import Dict, List, Set, Union
33

44
import pandas_ta as ta # noqa: F401
5-
from pydantic import field_validator
6-
from pydantic.v1 import Field, validator
5+
from pydantic import Field, field_validator
76

8-
from hummingbot.client.config.config_data_types import ClientFieldData
97
from hummingbot.core.data_type.common import OrderType, PositionMode, PriceType, TradeType
108
from hummingbot.data_feed.candles_feed.data_types import CandlesConfig
119
from hummingbot.strategy_v2.controllers import ControllerBase, ControllerConfigBase
@@ -21,34 +19,33 @@ class QGAConfig(ControllerConfigBase):
2119
candles_config: List[CandlesConfig] = []
2220

2321
# Portfolio allocation zones
24-
long_only_threshold: Decimal = Field(default=Decimal("0.2"), client_data=ClientFieldData(is_updatable=True))
25-
short_only_threshold: Decimal = Field(default=Decimal("0.2"), client_data=ClientFieldData(is_updatable=True))
26-
hedge_ratio: Decimal = Field(default=Decimal("2"), client_data=ClientFieldData(is_updatable=True))
22+
long_only_threshold: Decimal = Field(default=Decimal("0.2"), json_schema_extra={"is_updatable": True})
23+
short_only_threshold: Decimal = Field(default=Decimal("0.2"), json_schema_extra={"is_updatable": True})
24+
hedge_ratio: Decimal = Field(default=Decimal("2"), json_schema_extra={"is_updatable": True})
2725

2826
# Grid allocation multipliers
29-
base_grid_value_pct: Decimal = Field(default=Decimal("0.08"), client_data=ClientFieldData(is_updatable=True))
30-
max_grid_value_pct: Decimal = Field(default=Decimal("0.15"), client_data=ClientFieldData(is_updatable=True))
27+
base_grid_value_pct: Decimal = Field(default=Decimal("0.08"), json_schema_extra={"is_updatable": True})
28+
max_grid_value_pct: Decimal = Field(default=Decimal("0.15"), json_schema_extra={"is_updatable": True})
3129

3230
# Order frequency settings
33-
safe_extra_spread: Decimal = Field(default=Decimal("0.0001"), client_data=ClientFieldData(is_updatable=True))
34-
favorable_order_frequency: int = Field(default=2, client_data=ClientFieldData(is_updatable=True))
35-
unfavorable_order_frequency: int = Field(default=5, client_data=ClientFieldData(is_updatable=True))
36-
max_orders_per_batch: int = Field(default=1, client_data=ClientFieldData(is_updatable=True))
31+
safe_extra_spread: Decimal = Field(default=Decimal("0.0001"), json_schema_extra={"is_updatable": True})
32+
favorable_order_frequency: int = Field(default=2, json_schema_extra={"is_updatable": True})
33+
unfavorable_order_frequency: int = Field(default=5, json_schema_extra={"is_updatable": True})
34+
max_orders_per_batch: int = Field(default=1, json_schema_extra={"is_updatable": True})
3735

3836
# Portfolio allocation
3937
portfolio_allocation: Dict[str, Decimal] = Field(
4038
default={
4139
"SOL": Decimal("0.50"), # 50%
4240
},
43-
client_data=ClientFieldData(is_updatable=True)
44-
)
41+
json_schema_extra={"is_updatable": True})
4542
# Grid parameters
46-
grid_range: Decimal = Field(default=Decimal("0.002"), client_data=ClientFieldData(is_updatable=True))
47-
tp_sl_ratio: Decimal = Field(default=Decimal("0.8"), client_data=ClientFieldData(is_updatable=True))
48-
min_order_amount: Decimal = Field(default=Decimal("5"), client_data=ClientFieldData(is_updatable=True))
43+
grid_range: Decimal = Field(default=Decimal("0.002"), json_schema_extra={"is_updatable": True})
44+
tp_sl_ratio: Decimal = Field(default=Decimal("0.8"), json_schema_extra={"is_updatable": True})
45+
min_order_amount: Decimal = Field(default=Decimal("5"), json_schema_extra={"is_updatable": True})
4946
# Risk parameters
50-
max_deviation: Decimal = Field(default=Decimal("0.05"), client_data=ClientFieldData(is_updatable=True))
51-
max_open_orders: int = Field(default=2, client_data=ClientFieldData(is_updatable=True))
47+
max_deviation: Decimal = Field(default=Decimal("0.05"), json_schema_extra={"is_updatable": True})
48+
max_open_orders: int = Field(default=2, json_schema_extra={"is_updatable": True})
5249
# Exchange settings
5350
connector_name: str = "binance"
5451
leverage: int = 1
@@ -58,25 +55,21 @@ class QGAConfig(ControllerConfigBase):
5855
# Grid price multipliers
5956
min_spread_between_orders: Decimal = Field(
6057
default=Decimal("0.0001"), # 0.01% between orders
61-
client_data=ClientFieldData(is_updatable=True)
62-
)
58+
json_schema_extra={"is_updatable": True})
6359
grid_tp_multiplier: Decimal = Field(
6460
default=Decimal("0.0001"), # 0.2% take profit
65-
client_data=ClientFieldData(is_updatable=True)
66-
)
61+
json_schema_extra={"is_updatable": True})
6762
# Grid safety parameters
6863
limit_price_spread: Decimal = Field(
6964
default=Decimal("0.001"), # 0.1% spread for limit price
70-
client_data=ClientFieldData(is_updatable=True)
71-
)
65+
json_schema_extra={"is_updatable": True})
7266
activation_bounds: Decimal = Field(
7367
default=Decimal("0.0002"), # Activation bounds for orders
74-
client_data=ClientFieldData(is_updatable=True)
75-
)
68+
json_schema_extra={"is_updatable": True})
7669
bb_lenght: int = 100
7770
bb_std_dev: float = 2.0
7871
interval: str = "1s"
79-
dynamic_grid_range: bool = Field(default=False, client_data=ClientFieldData(is_updatable=True))
72+
dynamic_grid_range: bool = Field(default=False, json_schema_extra={"is_updatable": True})
8073
show_terminated_details: bool = False
8174

8275
@property

bots/controllers/generic/xemm_multiple_levels.py

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
from typing import Dict, List, Set
44

55
import pandas as pd
6-
from pydantic.v1 import Field, validator
6+
from pydantic import Field, field_validator
77

8-
from hummingbot.client.config.config_data_types import ClientFieldData
98
from hummingbot.client.ui.interface_utils import format_df_for_printout
109
from hummingbot.core.data_type.common import PriceType, TradeType
1110
from hummingbot.data_feed.candles_feed.data_types import CandlesConfig
@@ -20,63 +19,39 @@ class XEMMMultipleLevelsConfig(ControllerConfigBase):
2019
candles_config: List[CandlesConfig] = []
2120
maker_connector: str = Field(
2221
default="mexc",
23-
client_data=ClientFieldData(
24-
prompt=lambda e: "Enter the maker connector: ",
25-
prompt_on_new=True
26-
))
22+
json_schema_extra={"prompt": "Enter the maker connector: ", "prompt_on_new": True})
2723
maker_trading_pair: str = Field(
2824
default="PEPE-USDT",
29-
client_data=ClientFieldData(
30-
prompt=lambda e: "Enter the maker trading pair: ",
31-
prompt_on_new=True
32-
))
25+
json_schema_extra={"prompt": "Enter the maker trading pair: ", "prompt_on_new": True})
3326
taker_connector: str = Field(
3427
default="binance",
35-
client_data=ClientFieldData(
36-
prompt=lambda e: "Enter the taker connector: ",
37-
prompt_on_new=True
38-
))
28+
json_schema_extra={"prompt": "Enter the taker connector: ", "prompt_on_new": True})
3929
taker_trading_pair: str = Field(
4030
default="PEPE-USDT",
41-
client_data=ClientFieldData(
42-
prompt=lambda e: "Enter the taker trading pair: ",
43-
prompt_on_new=True
44-
))
31+
json_schema_extra={"prompt": "Enter the taker trading pair: ", "prompt_on_new": True})
4532
buy_levels_targets_amount: List[List[Decimal]] = Field(
4633
default="0.003,10-0.006,20-0.009,30",
47-
client_data=ClientFieldData(
48-
prompt=lambda e: "Enter the buy levels targets with the following structure: (target_profitability1,amount1-target_profitability2,amount2): ",
49-
prompt_on_new=True
50-
))
34+
json_schema_extra={
35+
"prompt": "Enter the buy levels targets with the following structure: (target_profitability1,amount1-target_profitability2,amount2): ",
36+
"prompt_on_new": True})
5137
sell_levels_targets_amount: List[List[Decimal]] = Field(
5238
default="0.003,10-0.006,20-0.009,30",
53-
client_data=ClientFieldData(
54-
prompt=lambda e: "Enter the sell levels targets with the following structure: (target_profitability1,amount1-target_profitability2,amount2): ",
55-
prompt_on_new=True
56-
))
39+
json_schema_extra={
40+
"prompt": "Enter the sell levels targets with the following structure: (target_profitability1,amount1-target_profitability2,amount2): ",
41+
"prompt_on_new": True})
5742
min_profitability: Decimal = Field(
5843
default=0.003,
59-
client_data=ClientFieldData(
60-
prompt=lambda e: "Enter the minimum profitability: ",
61-
prompt_on_new=True
62-
))
44+
json_schema_extra={"prompt": "Enter the minimum profitability: ", "prompt_on_new": True})
6345
max_profitability: Decimal = Field(
6446
default=0.01,
65-
client_data=ClientFieldData(
66-
prompt=lambda e: "Enter the maximum profitability: ",
67-
prompt_on_new=True
68-
))
47+
json_schema_extra={"prompt": "Enter the maximum profitability: ", "prompt_on_new": True})
6948
max_executors_imbalance: int = Field(
7049
default=1,
71-
client_data=ClientFieldData(
72-
prompt=lambda e: "Enter the maximum executors imbalance: ",
73-
prompt_on_new=True
74-
))
50+
json_schema_extra={"prompt": "Enter the maximum executors imbalance: ", "prompt_on_new": True})
7551

76-
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
77-
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
78-
@validator("buy_levels_targets_amount", "sell_levels_targets_amount", pre=True, always=True)
79-
def validate_levels_targets_amount(cls, v, values):
52+
@field_validator("buy_levels_targets_amount", "sell_levels_targets_amount", mode="before")
53+
@classmethod
54+
def validate_levels_targets_amount(cls, v):
8055
if isinstance(v, str):
8156
v = [list(map(Decimal, x.split(","))) for x in v.split("-")]
8257
return v

0 commit comments

Comments
 (0)