Merge pull request #9011 from freqtrade/dependabot/pip/develop/pydantic-2.1.1
Bump pydantic from 1.10.11 to 2.1.1
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, ConfigDict, RootModel, SerializeAsAny
|
||||||
|
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, IntOrInf
|
from freqtrade.constants import DATETIME_PRINT_FORMAT, IntOrInf
|
||||||
from freqtrade.enums import MarginMode, OrderTypeValues, SignalDirection, TradingMode
|
from freqtrade.enums import MarginMode, OrderTypeValues, SignalDirection, TradingMode
|
||||||
@@ -9,9 +9,9 @@ from freqtrade.types import ValidExchangesType
|
|||||||
|
|
||||||
|
|
||||||
class ExchangeModePayloadMixin(BaseModel):
|
class ExchangeModePayloadMixin(BaseModel):
|
||||||
trading_mode: Optional[TradingMode]
|
trading_mode: Optional[TradingMode] = None
|
||||||
margin_mode: Optional[MarginMode]
|
margin_mode: Optional[MarginMode] = None
|
||||||
exchange: Optional[str]
|
exchange: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class Ping(BaseModel):
|
class Ping(BaseModel):
|
||||||
@@ -43,11 +43,11 @@ class BackgroundTaskStatus(BaseModel):
|
|||||||
job_category: str
|
job_category: str
|
||||||
status: str
|
status: str
|
||||||
running: bool
|
running: bool
|
||||||
progress: Optional[float]
|
progress: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
class BackgroundTaskResult(BaseModel):
|
class BackgroundTaskResult(BaseModel):
|
||||||
error: Optional[str]
|
error: Optional[str] = None
|
||||||
status: str
|
status: str
|
||||||
|
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ class Balance(BaseModel):
|
|||||||
free: float
|
free: float
|
||||||
balance: float
|
balance: float
|
||||||
used: float
|
used: float
|
||||||
bot_owned: Optional[float]
|
bot_owned: Optional[float] = None
|
||||||
est_stake: float
|
est_stake: float
|
||||||
est_stake_bot: Optional[float]
|
est_stake_bot: Optional[float] = None
|
||||||
stake: str
|
stake: str
|
||||||
# Starting with 2.x
|
# Starting with 2.x
|
||||||
side: str
|
side: str
|
||||||
@@ -141,7 +141,7 @@ class Profit(BaseModel):
|
|||||||
expectancy_ratio: float
|
expectancy_ratio: float
|
||||||
max_drawdown: float
|
max_drawdown: float
|
||||||
max_drawdown_abs: float
|
max_drawdown_abs: float
|
||||||
trading_volume: Optional[float]
|
trading_volume: Optional[float] = None
|
||||||
bot_start_timestamp: int
|
bot_start_timestamp: int
|
||||||
bot_start_date: str
|
bot_start_date: str
|
||||||
|
|
||||||
@@ -173,50 +173,50 @@ class Daily(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class UnfilledTimeout(BaseModel):
|
class UnfilledTimeout(BaseModel):
|
||||||
entry: Optional[int]
|
entry: Optional[int] = None
|
||||||
exit: Optional[int]
|
exit: Optional[int] = None
|
||||||
unit: Optional[str]
|
unit: Optional[str] = None
|
||||||
exit_timeout_count: Optional[int]
|
exit_timeout_count: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
class OrderTypes(BaseModel):
|
class OrderTypes(BaseModel):
|
||||||
entry: OrderTypeValues
|
entry: OrderTypeValues
|
||||||
exit: OrderTypeValues
|
exit: OrderTypeValues
|
||||||
emergency_exit: Optional[OrderTypeValues]
|
emergency_exit: Optional[OrderTypeValues] = None
|
||||||
force_exit: Optional[OrderTypeValues]
|
force_exit: Optional[OrderTypeValues] = None
|
||||||
force_entry: Optional[OrderTypeValues]
|
force_entry: Optional[OrderTypeValues] = None
|
||||||
stoploss: OrderTypeValues
|
stoploss: OrderTypeValues
|
||||||
stoploss_on_exchange: bool
|
stoploss_on_exchange: bool
|
||||||
stoploss_on_exchange_interval: Optional[int]
|
stoploss_on_exchange_interval: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
class ShowConfig(BaseModel):
|
class ShowConfig(BaseModel):
|
||||||
version: str
|
version: str
|
||||||
strategy_version: Optional[str]
|
strategy_version: Optional[str] = None
|
||||||
api_version: float
|
api_version: float
|
||||||
dry_run: bool
|
dry_run: bool
|
||||||
trading_mode: str
|
trading_mode: str
|
||||||
short_allowed: bool
|
short_allowed: bool
|
||||||
stake_currency: str
|
stake_currency: str
|
||||||
stake_amount: str
|
stake_amount: str
|
||||||
available_capital: Optional[float]
|
available_capital: Optional[float] = None
|
||||||
stake_currency_decimals: int
|
stake_currency_decimals: int
|
||||||
max_open_trades: IntOrInf
|
max_open_trades: IntOrInf
|
||||||
minimal_roi: Dict[str, Any]
|
minimal_roi: Dict[str, Any]
|
||||||
stoploss: Optional[float]
|
stoploss: Optional[float] = None
|
||||||
stoploss_on_exchange: bool
|
stoploss_on_exchange: bool
|
||||||
trailing_stop: Optional[bool]
|
trailing_stop: Optional[bool] = None
|
||||||
trailing_stop_positive: Optional[float]
|
trailing_stop_positive: Optional[float] = None
|
||||||
trailing_stop_positive_offset: Optional[float]
|
trailing_stop_positive_offset: Optional[float] = None
|
||||||
trailing_only_offset_is_reached: Optional[bool]
|
trailing_only_offset_is_reached: Optional[bool] = None
|
||||||
unfilledtimeout: Optional[UnfilledTimeout] # Empty in webserver mode
|
unfilledtimeout: Optional[UnfilledTimeout] = None # Empty in webserver mode
|
||||||
order_types: Optional[OrderTypes]
|
order_types: Optional[OrderTypes] = None
|
||||||
use_custom_stoploss: Optional[bool]
|
use_custom_stoploss: Optional[bool] = None
|
||||||
timeframe: Optional[str]
|
timeframe: Optional[str] = None
|
||||||
timeframe_ms: int
|
timeframe_ms: int
|
||||||
timeframe_min: int
|
timeframe_min: int
|
||||||
exchange: str
|
exchange: str
|
||||||
strategy: Optional[str]
|
strategy: Optional[str] = None
|
||||||
force_entry_enable: bool
|
force_entry_enable: bool
|
||||||
exit_pricing: Dict[str, Any]
|
exit_pricing: Dict[str, Any]
|
||||||
entry_pricing: Dict[str, Any]
|
entry_pricing: Dict[str, Any]
|
||||||
@@ -231,17 +231,17 @@ class OrderSchema(BaseModel):
|
|||||||
pair: str
|
pair: str
|
||||||
order_id: str
|
order_id: str
|
||||||
status: str
|
status: str
|
||||||
remaining: Optional[float]
|
remaining: Optional[float] = None
|
||||||
amount: float
|
amount: float
|
||||||
safe_price: float
|
safe_price: float
|
||||||
cost: float
|
cost: float
|
||||||
filled: Optional[float]
|
filled: Optional[float] = None
|
||||||
ft_order_side: str
|
ft_order_side: str
|
||||||
order_type: str
|
order_type: str
|
||||||
is_open: bool
|
is_open: bool
|
||||||
order_timestamp: Optional[int]
|
order_timestamp: Optional[int] = None
|
||||||
order_filled_timestamp: Optional[int]
|
order_filled_timestamp: Optional[int] = None
|
||||||
ft_fee_base: Optional[float]
|
ft_fee_base: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
class TradeSchema(BaseModel):
|
class TradeSchema(BaseModel):
|
||||||
@@ -255,81 +255,81 @@ class TradeSchema(BaseModel):
|
|||||||
amount: float
|
amount: float
|
||||||
amount_requested: float
|
amount_requested: float
|
||||||
stake_amount: float
|
stake_amount: float
|
||||||
max_stake_amount: Optional[float]
|
max_stake_amount: Optional[float] = None
|
||||||
strategy: str
|
strategy: str
|
||||||
enter_tag: Optional[str]
|
enter_tag: Optional[str] = None
|
||||||
timeframe: int
|
timeframe: int
|
||||||
fee_open: Optional[float]
|
fee_open: Optional[float] = None
|
||||||
fee_open_cost: Optional[float]
|
fee_open_cost: Optional[float] = None
|
||||||
fee_open_currency: Optional[str]
|
fee_open_currency: Optional[str] = None
|
||||||
fee_close: Optional[float]
|
fee_close: Optional[float] = None
|
||||||
fee_close_cost: Optional[float]
|
fee_close_cost: Optional[float] = None
|
||||||
fee_close_currency: Optional[str]
|
fee_close_currency: Optional[str] = None
|
||||||
|
|
||||||
open_date: str
|
open_date: str
|
||||||
open_timestamp: int
|
open_timestamp: int
|
||||||
open_rate: float
|
open_rate: float
|
||||||
open_rate_requested: Optional[float]
|
open_rate_requested: Optional[float] = None
|
||||||
open_trade_value: float
|
open_trade_value: float
|
||||||
|
|
||||||
close_date: Optional[str]
|
close_date: Optional[str] = None
|
||||||
close_timestamp: Optional[int]
|
close_timestamp: Optional[int] = None
|
||||||
close_rate: Optional[float]
|
close_rate: Optional[float] = None
|
||||||
close_rate_requested: Optional[float]
|
close_rate_requested: Optional[float] = None
|
||||||
|
|
||||||
close_profit: Optional[float]
|
close_profit: Optional[float] = None
|
||||||
close_profit_pct: Optional[float]
|
close_profit_pct: Optional[float] = None
|
||||||
close_profit_abs: Optional[float]
|
close_profit_abs: Optional[float] = None
|
||||||
|
|
||||||
profit_ratio: Optional[float]
|
profit_ratio: Optional[float] = None
|
||||||
profit_pct: Optional[float]
|
profit_pct: Optional[float] = None
|
||||||
profit_abs: Optional[float]
|
profit_abs: Optional[float] = None
|
||||||
profit_fiat: Optional[float]
|
profit_fiat: Optional[float] = None
|
||||||
|
|
||||||
realized_profit: float
|
realized_profit: float
|
||||||
realized_profit_ratio: Optional[float]
|
realized_profit_ratio: Optional[float] = None
|
||||||
|
|
||||||
exit_reason: Optional[str]
|
exit_reason: Optional[str] = None
|
||||||
exit_order_status: Optional[str]
|
exit_order_status: Optional[str] = None
|
||||||
|
|
||||||
stop_loss_abs: Optional[float]
|
stop_loss_abs: Optional[float] = None
|
||||||
stop_loss_ratio: Optional[float]
|
stop_loss_ratio: Optional[float] = None
|
||||||
stop_loss_pct: Optional[float]
|
stop_loss_pct: Optional[float] = None
|
||||||
stoploss_order_id: Optional[str]
|
stoploss_order_id: Optional[str] = None
|
||||||
stoploss_last_update: Optional[str]
|
stoploss_last_update: Optional[str] = None
|
||||||
stoploss_last_update_timestamp: Optional[int]
|
stoploss_last_update_timestamp: Optional[int] = None
|
||||||
initial_stop_loss_abs: Optional[float]
|
initial_stop_loss_abs: Optional[float] = None
|
||||||
initial_stop_loss_ratio: Optional[float]
|
initial_stop_loss_ratio: Optional[float] = None
|
||||||
initial_stop_loss_pct: Optional[float]
|
initial_stop_loss_pct: Optional[float] = None
|
||||||
|
|
||||||
min_rate: Optional[float]
|
min_rate: Optional[float] = None
|
||||||
max_rate: Optional[float]
|
max_rate: Optional[float] = None
|
||||||
open_order_id: Optional[str]
|
open_order_id: Optional[str] = None
|
||||||
orders: List[OrderSchema]
|
orders: List[OrderSchema]
|
||||||
|
|
||||||
leverage: Optional[float]
|
leverage: Optional[float] = None
|
||||||
interest_rate: Optional[float]
|
interest_rate: Optional[float] = None
|
||||||
liquidation_price: Optional[float]
|
liquidation_price: Optional[float] = None
|
||||||
funding_fees: Optional[float]
|
funding_fees: Optional[float] = None
|
||||||
trading_mode: Optional[TradingMode]
|
trading_mode: Optional[TradingMode] = None
|
||||||
|
|
||||||
amount_precision: Optional[float]
|
amount_precision: Optional[float] = None
|
||||||
price_precision: Optional[float]
|
price_precision: Optional[float] = None
|
||||||
precision_mode: Optional[int]
|
precision_mode: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
class OpenTradeSchema(TradeSchema):
|
class OpenTradeSchema(TradeSchema):
|
||||||
stoploss_current_dist: Optional[float]
|
stoploss_current_dist: Optional[float] = None
|
||||||
stoploss_current_dist_pct: Optional[float]
|
stoploss_current_dist_pct: Optional[float] = None
|
||||||
stoploss_current_dist_ratio: Optional[float]
|
stoploss_current_dist_ratio: Optional[float] = None
|
||||||
stoploss_entry_dist: Optional[float]
|
stoploss_entry_dist: Optional[float] = None
|
||||||
stoploss_entry_dist_ratio: Optional[float]
|
stoploss_entry_dist_ratio: Optional[float] = None
|
||||||
current_rate: float
|
current_rate: float
|
||||||
total_profit_abs: float
|
total_profit_abs: float
|
||||||
total_profit_fiat: Optional[float]
|
total_profit_fiat: Optional[float] = None
|
||||||
total_profit_ratio: Optional[float]
|
total_profit_ratio: Optional[float] = None
|
||||||
|
|
||||||
open_order: Optional[str]
|
open_order: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class TradeResponse(BaseModel):
|
class TradeResponse(BaseModel):
|
||||||
@@ -339,8 +339,7 @@ class TradeResponse(BaseModel):
|
|||||||
total_trades: int
|
total_trades: int
|
||||||
|
|
||||||
|
|
||||||
class ForceEnterResponse(BaseModel):
|
ForceEnterResponse = RootModel[Union[TradeSchema, StatusMsg]]
|
||||||
__root__: Union[TradeSchema, StatusMsg]
|
|
||||||
|
|
||||||
|
|
||||||
class LockModel(BaseModel):
|
class LockModel(BaseModel):
|
||||||
@@ -352,7 +351,7 @@ class LockModel(BaseModel):
|
|||||||
lock_timestamp: int
|
lock_timestamp: int
|
||||||
pair: str
|
pair: str
|
||||||
side: str
|
side: str
|
||||||
reason: Optional[str]
|
reason: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class Locks(BaseModel):
|
class Locks(BaseModel):
|
||||||
@@ -361,8 +360,8 @@ class Locks(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class DeleteLockRequest(BaseModel):
|
class DeleteLockRequest(BaseModel):
|
||||||
pair: Optional[str]
|
pair: Optional[str] = None
|
||||||
lockid: Optional[int]
|
lockid: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
class Logs(BaseModel):
|
class Logs(BaseModel):
|
||||||
@@ -373,17 +372,17 @@ class Logs(BaseModel):
|
|||||||
class ForceEnterPayload(BaseModel):
|
class ForceEnterPayload(BaseModel):
|
||||||
pair: str
|
pair: str
|
||||||
side: SignalDirection = SignalDirection.LONG
|
side: SignalDirection = SignalDirection.LONG
|
||||||
price: Optional[float]
|
price: Optional[float] = None
|
||||||
ordertype: Optional[OrderTypeValues]
|
ordertype: Optional[OrderTypeValues] = None
|
||||||
stakeamount: Optional[float]
|
stakeamount: Optional[float] = None
|
||||||
entry_tag: Optional[str]
|
entry_tag: Optional[str] = None
|
||||||
leverage: Optional[float]
|
leverage: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
class ForceExitPayload(BaseModel):
|
class ForceExitPayload(BaseModel):
|
||||||
tradeid: str
|
tradeid: str
|
||||||
ordertype: Optional[OrderTypeValues]
|
ordertype: Optional[OrderTypeValues] = None
|
||||||
amount: Optional[float]
|
amount: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
class BlacklistPayload(BaseModel):
|
class BlacklistPayload(BaseModel):
|
||||||
@@ -405,7 +404,7 @@ class WhitelistResponse(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class WhitelistEvaluateResponse(BackgroundTaskResult):
|
class WhitelistEvaluateResponse(BackgroundTaskResult):
|
||||||
result: Optional[WhitelistResponse]
|
result: Optional[WhitelistResponse] = None
|
||||||
|
|
||||||
|
|
||||||
class DeleteTrade(BaseModel):
|
class DeleteTrade(BaseModel):
|
||||||
@@ -420,8 +419,7 @@ class PlotConfig_(BaseModel):
|
|||||||
subplots: Dict[str, Any]
|
subplots: Dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
class PlotConfig(BaseModel):
|
PlotConfig = RootModel[Union[PlotConfig_, Dict]]
|
||||||
__root__: Union[PlotConfig_, Dict]
|
|
||||||
|
|
||||||
|
|
||||||
class StrategyListResponse(BaseModel):
|
class StrategyListResponse(BaseModel):
|
||||||
@@ -470,7 +468,7 @@ class PairHistory(BaseModel):
|
|||||||
timeframe: str
|
timeframe: str
|
||||||
timeframe_ms: int
|
timeframe_ms: int
|
||||||
columns: List[str]
|
columns: List[str]
|
||||||
data: List[Any]
|
data: SerializeAsAny[List[Any]]
|
||||||
length: int
|
length: int
|
||||||
buy_signals: int
|
buy_signals: int
|
||||||
sell_signals: int
|
sell_signals: int
|
||||||
@@ -484,11 +482,11 @@ class PairHistory(BaseModel):
|
|||||||
data_start: str
|
data_start: str
|
||||||
data_stop: str
|
data_stop: str
|
||||||
data_stop_ts: int
|
data_stop_ts: int
|
||||||
|
# TODO[pydantic]: The following keys were removed: `json_encoders`.
|
||||||
class Config:
|
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
|
||||||
json_encoders = {
|
model_config = ConfigDict(json_encoders={
|
||||||
datetime: lambda v: v.strftime(DATETIME_PRINT_FORMAT),
|
datetime: lambda v: v.strftime(DATETIME_PRINT_FORMAT),
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
class BacktestFreqAIInputs(BaseModel):
|
class BacktestFreqAIInputs(BaseModel):
|
||||||
@@ -497,16 +495,16 @@ class BacktestFreqAIInputs(BaseModel):
|
|||||||
|
|
||||||
class BacktestRequest(BaseModel):
|
class BacktestRequest(BaseModel):
|
||||||
strategy: str
|
strategy: str
|
||||||
timeframe: Optional[str]
|
timeframe: Optional[str] = None
|
||||||
timeframe_detail: Optional[str]
|
timeframe_detail: Optional[str] = None
|
||||||
timerange: Optional[str]
|
timerange: Optional[str] = None
|
||||||
max_open_trades: Optional[IntOrInf]
|
max_open_trades: Optional[IntOrInf] = None
|
||||||
stake_amount: Optional[str]
|
stake_amount: Optional[Union[str, float]] = None
|
||||||
enable_protections: bool
|
enable_protections: bool
|
||||||
dry_run_wallet: Optional[float]
|
dry_run_wallet: Optional[float] = None
|
||||||
backtest_cache: Optional[str]
|
backtest_cache: Optional[str] = None
|
||||||
freqaimodel: Optional[str]
|
freqaimodel: Optional[str] = None
|
||||||
freqai: Optional[BacktestFreqAIInputs]
|
freqai: Optional[BacktestFreqAIInputs] = None
|
||||||
|
|
||||||
|
|
||||||
class BacktestResponse(BaseModel):
|
class BacktestResponse(BaseModel):
|
||||||
@@ -515,9 +513,9 @@ class BacktestResponse(BaseModel):
|
|||||||
status_msg: str
|
status_msg: str
|
||||||
step: str
|
step: str
|
||||||
progress: float
|
progress: float
|
||||||
trade_count: Optional[float]
|
trade_count: Optional[float] = None
|
||||||
# TODO: Properly type backtestresult...
|
# TODO: Properly type backtestresult...
|
||||||
backtest_result: Optional[Dict[str, Any]]
|
backtest_result: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
|
|
||||||
# TODO: This is a copy of BacktestHistoryEntryType
|
# TODO: This is a copy of BacktestHistoryEntryType
|
||||||
@@ -540,5 +538,5 @@ class SysInfo(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class Health(BaseModel):
|
class Health(BaseModel):
|
||||||
last_process: Optional[datetime]
|
last_process: Optional[datetime] = None
|
||||||
last_process_ts: Optional[int]
|
last_process_ts: Optional[int] = None
|
||||||
|
|||||||
@@ -175,9 +175,9 @@ def force_entry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)):
|
|||||||
leverage=payload.leverage)
|
leverage=payload.leverage)
|
||||||
|
|
||||||
if trade:
|
if trade:
|
||||||
return ForceEnterResponse.parse_obj(trade.to_json())
|
return ForceEnterResponse.model_validate(trade.to_json())
|
||||||
else:
|
else:
|
||||||
return ForceEnterResponse.parse_obj(
|
return ForceEnterResponse.model_validate(
|
||||||
{"status": f"Error entering {payload.side} trade for pair {payload.pair}."})
|
{"status": f"Error entering {payload.side} trade for pair {payload.pair}."})
|
||||||
|
|
||||||
|
|
||||||
@@ -282,14 +282,14 @@ def plot_config(strategy: Optional[str] = None, config=Depends(get_config),
|
|||||||
if not strategy:
|
if not strategy:
|
||||||
if not rpc:
|
if not rpc:
|
||||||
raise RPCException("Strategy is mandatory in webserver mode.")
|
raise RPCException("Strategy is mandatory in webserver mode.")
|
||||||
return PlotConfig.parse_obj(rpc._rpc_plot_config())
|
return PlotConfig.model_validate(rpc._rpc_plot_config())
|
||||||
else:
|
else:
|
||||||
config1 = deepcopy(config)
|
config1 = deepcopy(config)
|
||||||
config1.update({
|
config1.update({
|
||||||
'strategy': strategy
|
'strategy': strategy
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
return PlotConfig.parse_obj(RPC._rpc_plot_config_with_strategy(config1))
|
return PlotConfig.model_validate(RPC._rpc_plot_config_with_strategy(config1))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=502, detail=str(e))
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ async def _process_consumer_request(
|
|||||||
"""
|
"""
|
||||||
# Validate the request, makes sure it matches the schema
|
# Validate the request, makes sure it matches the schema
|
||||||
try:
|
try:
|
||||||
websocket_request = WSRequestSchema.parse_obj(request)
|
websocket_request = WSRequestSchema.model_validate(request)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logger.error(f"Invalid request from {channel}: {e}")
|
logger.error(f"Invalid request from {channel}: {e}")
|
||||||
return
|
return
|
||||||
@@ -94,7 +94,7 @@ async def _process_consumer_request(
|
|||||||
|
|
||||||
# Format response
|
# Format response
|
||||||
response = WSWhitelistMessage(data=whitelist)
|
response = WSWhitelistMessage(data=whitelist)
|
||||||
await channel.send(response.dict(exclude_none=True))
|
await channel.send(response.model_dump(exclude_none=True))
|
||||||
|
|
||||||
elif type_ == RPCRequestType.ANALYZED_DF:
|
elif type_ == RPCRequestType.ANALYZED_DF:
|
||||||
# Limit the amount of candles per dataframe to 'limit' or 1500
|
# Limit the amount of candles per dataframe to 'limit' or 1500
|
||||||
@@ -105,7 +105,7 @@ async def _process_consumer_request(
|
|||||||
for message in rpc._ws_request_analyzed_df(limit, pair):
|
for message in rpc._ws_request_analyzed_df(limit, pair):
|
||||||
# Format response
|
# Format response
|
||||||
response = WSAnalyzedDFMessage(data=message)
|
response = WSAnalyzedDFMessage(data=message)
|
||||||
await channel.send(response.dict(exclude_none=True))
|
await channel.send(response.model_dump(exclude_none=True))
|
||||||
|
|
||||||
|
|
||||||
@router.websocket("/message/ws")
|
@router.websocket("/message/ws")
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ from datetime import datetime
|
|||||||
from typing import Any, Dict, List, Optional, TypedDict
|
from typing import Any, Dict, List, Optional, TypedDict
|
||||||
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, ConfigDict
|
||||||
|
|
||||||
from freqtrade.constants import PairWithTimeframe
|
from freqtrade.constants import PairWithTimeframe
|
||||||
from freqtrade.enums.rpcmessagetype import RPCMessageType, RPCRequestType
|
from freqtrade.enums.rpcmessagetype import RPCMessageType, RPCRequestType
|
||||||
|
|
||||||
|
|
||||||
class BaseArbitraryModel(BaseModel):
|
class BaseArbitraryModel(BaseModel):
|
||||||
class Config:
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||||
arbitrary_types_allowed = True
|
|
||||||
|
|
||||||
|
|
||||||
class WSRequestSchema(BaseArbitraryModel):
|
class WSRequestSchema(BaseArbitraryModel):
|
||||||
@@ -27,9 +26,7 @@ class WSMessageSchemaType(TypedDict):
|
|||||||
class WSMessageSchema(BaseArbitraryModel):
|
class WSMessageSchema(BaseArbitraryModel):
|
||||||
type: RPCMessageType
|
type: RPCMessageType
|
||||||
data: Optional[Any] = None
|
data: Optional[Any] = None
|
||||||
|
model_config = ConfigDict(extra='allow')
|
||||||
class Config:
|
|
||||||
extra = 'allow'
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------ REQUEST SCHEMAS ----------------------------
|
# ------------------------------ REQUEST SCHEMAS ----------------------------
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def schema_to_dict(schema: Union[WSMessageSchema, WSRequestSchema]):
|
def schema_to_dict(schema: Union[WSMessageSchema, WSRequestSchema]):
|
||||||
return schema.dict(exclude_none=True)
|
return schema.model_dump(exclude_none=True)
|
||||||
|
|
||||||
|
|
||||||
class ExternalMessageConsumer:
|
class ExternalMessageConsumer:
|
||||||
@@ -322,7 +322,7 @@ class ExternalMessageConsumer:
|
|||||||
producer_name = producer.get('name', 'default')
|
producer_name = producer.get('name', 'default')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
producer_message = WSMessageSchema.parse_obj(message)
|
producer_message = WSMessageSchema.model_validate(message)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
||||||
return
|
return
|
||||||
@@ -344,7 +344,7 @@ class ExternalMessageConsumer:
|
|||||||
def _consume_whitelist_message(self, producer_name: str, message: WSMessageSchema):
|
def _consume_whitelist_message(self, producer_name: str, message: WSMessageSchema):
|
||||||
try:
|
try:
|
||||||
# Validate the message
|
# Validate the message
|
||||||
whitelist_message = WSWhitelistMessage.parse_obj(message)
|
whitelist_message = WSWhitelistMessage.model_validate(message.model_dump())
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
||||||
return
|
return
|
||||||
@@ -356,7 +356,7 @@ class ExternalMessageConsumer:
|
|||||||
|
|
||||||
def _consume_analyzed_df_message(self, producer_name: str, message: WSMessageSchema):
|
def _consume_analyzed_df_message(self, producer_name: str, message: WSMessageSchema):
|
||||||
try:
|
try:
|
||||||
df_message = WSAnalyzedDFMessage.parse_obj(message)
|
df_message = WSAnalyzedDFMessage.model_validate(message.model_dump())
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
logger.error(f"Invalid message from `{producer_name}`: {e}")
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ sdnotify==0.3.2
|
|||||||
|
|
||||||
# API Server
|
# API Server
|
||||||
fastapi==0.101.0
|
fastapi==0.101.0
|
||||||
pydantic==1.10.11
|
pydantic==2.2.0
|
||||||
uvicorn==0.23.2
|
uvicorn==0.23.2
|
||||||
pyjwt==2.8.0
|
pyjwt==2.8.0
|
||||||
aiofiles==23.2.1
|
aiofiles==23.2.1
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ setup(
|
|||||||
'rich',
|
'rich',
|
||||||
'pyarrow; platform_machine != "armv7l"',
|
'pyarrow; platform_machine != "armv7l"',
|
||||||
'fastapi',
|
'fastapi',
|
||||||
'pydantic>=1.8.0,<2.0',
|
'pydantic>=2.2.0',
|
||||||
'uvicorn',
|
'uvicorn',
|
||||||
'psutil',
|
'psutil',
|
||||||
'pyjwt',
|
'pyjwt',
|
||||||
|
|||||||
@@ -1429,12 +1429,12 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
|||||||
assert len(rc.json()['data']) == amount
|
assert len(rc.json()['data']) == amount
|
||||||
|
|
||||||
assert (rc.json()['data'] ==
|
assert (rc.json()['data'] ==
|
||||||
[['2017-11-26 08:50:00', 8.794e-05, 8.948e-05, 8.794e-05, 8.88e-05, 0.0877869,
|
[['2017-11-26T08:50:00Z', 8.794e-05, 8.948e-05, 8.794e-05, 8.88e-05, 0.0877869,
|
||||||
None, 0, 0, 0, 0, 1511686200000, None, None, None, None],
|
None, 0, 0, 0, 0, 1511686200000, None, None, None, None],
|
||||||
['2017-11-26 08:55:00', 8.88e-05, 8.942e-05, 8.88e-05,
|
['2017-11-26T08:55:00Z', 8.88e-05, 8.942e-05, 8.88e-05,
|
||||||
8.893e-05, 0.05874751, 8.886500000000001e-05, 1, 0, 0, 0, 1511686500000, 8.893e-05,
|
8.893e-05, 0.05874751, 8.886500000000001e-05, 1, 0, 0, 0, 1511686500000, 8.893e-05,
|
||||||
None, None, None],
|
None, None, None],
|
||||||
['2017-11-26 09:00:00', 8.891e-05, 8.893e-05, 8.875e-05, 8.877e-05,
|
['2017-11-26T09:00:00Z', 8.891e-05, 8.893e-05, 8.875e-05, 8.877e-05,
|
||||||
0.7039405, 8.885e-05, 0, 0, 0, 0, 1511686800000, None, None, None, None]
|
0.7039405, 8.885e-05, 0, 0, 0, 0, 1511686800000, None, None, None, None]
|
||||||
|
|
||||||
])
|
])
|
||||||
@@ -1448,13 +1448,13 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
|||||||
f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
|
f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert (rc.json()['data'] ==
|
assert (rc.json()['data'] ==
|
||||||
[['2017-11-26 08:50:00', 8.794e-05, 8.948e-05, 8.794e-05, 8.88e-05, 0.0877869,
|
[['2017-11-26T08:50:00Z', 8.794e-05, 8.948e-05, 8.794e-05, 8.88e-05, 0.0877869,
|
||||||
None, 0, None, 0, 0, None, 1511686200000, None, None, None, None],
|
None, 0, None, 0, 0, None, 1511686200000, None, None, None, None],
|
||||||
['2017-11-26 08:55:00', 8.88e-05, 8.942e-05, 8.88e-05,
|
['2017-11-26T08:55:00Z', 8.88e-05, 8.942e-05, 8.88e-05,
|
||||||
8.893e-05, 0.05874751, 8.886500000000001e-05, 1, 0.0, 0, 0, '2017-11-26 08:55:00',
|
8.893e-05, 0.05874751, 8.886500000000001e-05, 1, 0.0, 0, 0, '2017-11-26T08:55:00Z',
|
||||||
1511686500000, 8.893e-05, None, None, None],
|
1511686500000, 8.893e-05, None, None, None],
|
||||||
['2017-11-26 09:00:00', 8.891e-05, 8.893e-05, 8.875e-05, 8.877e-05,
|
['2017-11-26T09:00:00Z', 8.891e-05, 8.893e-05, 8.875e-05, 8.877e-05,
|
||||||
0.7039405, 8.885e-05, 0, 0.0, 0, 0, '2017-11-26 09:00:00', 1511686800000,
|
0.7039405, 8.885e-05, 0, 0.0, 0, 0, '2017-11-26T09:00:00Z', 1511686800000,
|
||||||
None, None, None, None]
|
None, None, None, None]
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -1511,7 +1511,7 @@ def test_api_pair_history(botclient, mocker):
|
|||||||
date_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'date'][0]
|
date_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'date'][0]
|
||||||
rsi_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'rsi'][0]
|
rsi_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'rsi'][0]
|
||||||
|
|
||||||
assert data[0][date_col_idx] == '2018-01-11 00:00:00'
|
assert data[0][date_col_idx] == '2018-01-11T00:00:00Z'
|
||||||
assert data[0][rsi_col_idx] is not None
|
assert data[0][rsi_col_idx] is not None
|
||||||
assert data[0][rsi_col_idx] > 0
|
assert data[0][rsi_col_idx] > 0
|
||||||
assert lfm.call_count == 1
|
assert lfm.call_count == 1
|
||||||
|
|||||||
Reference in New Issue
Block a user