Coverage for core/models/broker.py: 94.26%
122 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-13 18:58 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-13 18:58 +0000
1"""
2券商数据模型
3"""
5from datetime import datetime
6from decimal import Decimal
7from enum import Enum
8from typing import Any, Dict, Optional
10from pydantic import BaseModel, Field
13class BrokerType(str, Enum):
14 """券商类型枚举"""
16 LONGPORT = "longport"
17 OTHER = "other"
20class BrokerStatus(str, Enum):
21 """券商状态枚举"""
23 ACTIVE = "active"
24 INACTIVE = "inactive"
27class LanguageType(str, Enum):
28 """语言类型枚举"""
30 ZH_CN = "zh-CN"
31 ZH_HK = "zh-HK"
32 EN = "en"
35class USFeeConfig(BaseModel):
36 """美股交易费用配置"""
38 # 平台费用
39 platform_fee_per_share: Decimal = Field(
40 default=Decimal("0.005"), description="平台费(美元/股)"
41 )
42 platform_fee_minimum: Decimal = Field(
43 default=Decimal("1.0"), description="最低收取平台费(美元)"
44 )
46 # 交易活动费用(仅在卖出时收取)
47 activity_fee_per_share: Decimal = Field(
48 default=Decimal("0.000166"), description="交易活动费(美元/股,仅卖出)"
49 )
50 activity_fee_maximum: Decimal = Field(
51 default=Decimal("8.3"), description="最高收取交易活动费(美元)"
52 )
54 # 交收费
55 clearing_fee_per_share: Decimal = Field(
56 default=Decimal("0.003"), description="交收费(美元/股)"
57 )
58 clearing_fee_max_pct: Decimal = Field(
59 default=Decimal("0.07"), description="交收费最高收取百分比(7%)"
60 )
62 # 综合审计费
63 audit_fee_per_share: Decimal = Field(
64 default=Decimal("0.000046"), description="综合审计费(美元/股)"
65 )
66 audit_fee_minimum: Decimal = Field(
67 default=Decimal("0.01"), description="每笔订单最低收取综合审计费(美元)"
68 )
71class HKFeeConfig(BaseModel):
72 """港股交易费用配置"""
74 # 平台费用
75 platform_fee_per_share: Decimal = Field(
76 default=Decimal("0.005"), description="平台费(港元/股)"
77 )
78 platform_fee_minimum: Decimal = Field(
79 default=Decimal("1.0"), description="最低收取平台费(港元)"
80 )
82 # 交易活动费用(仅在卖出时收取)
83 activity_fee_per_share: Decimal = Field(
84 default=Decimal("0.000166"), description="交易活动费(港元/股,仅卖出)"
85 )
86 activity_fee_maximum: Decimal = Field(
87 default=Decimal("8.3"), description="最高收取交易活动费(港元)"
88 )
90 # 交收费
91 clearing_fee_per_share: Decimal = Field(
92 default=Decimal("0.003"), description="交收费(港元/股)"
93 )
94 clearing_fee_max_pct: Decimal = Field(
95 default=Decimal("0.07"), description="交收费最高收取百分比(7%)"
96 )
98 # 综合审计费
99 audit_fee_per_share: Decimal = Field(
100 default=Decimal("0.000046"), description="综合审计费(港元/股)"
101 )
102 audit_fee_minimum: Decimal = Field(
103 default=Decimal("0.01"), description="每笔订单最低收取综合审计费(港元)"
104 )
107class FeeConfig(BaseModel):
108 """交易费用配置"""
110 us_fees: USFeeConfig = Field(
111 default_factory=USFeeConfig, description="美股费用配置"
112 )
113 hk_fees: HKFeeConfig = Field(
114 default_factory=HKFeeConfig, description="港股费用配置"
115 )
118class BrokerConfig(BaseModel):
119 """券商配置(通用JSON配置)"""
121 config: dict = Field(..., description="券商配置JSON")
122 fee_config: Optional[FeeConfig] = Field(
123 default_factory=FeeConfig, description="交易费用配置"
124 )
127class BrokerBase(BaseModel):
128 """券商基础模型"""
130 name: str = Field(..., min_length=1, max_length=100, description="券商名称")
131 code: str = Field(..., min_length=1, max_length=50, description="券商代码")
132 type: BrokerType = Field(..., description="券商类型")
133 status: BrokerStatus = Field(BrokerStatus.ACTIVE, description="状态")
134 config: BrokerConfig = Field(..., description="券商配置")
135 user_id: str = Field(..., description="所属用户ID")
138class BrokerCreate(BrokerBase):
139 """创建券商模型"""
141 pass
144class BrokerUpdate(BaseModel):
145 """更新券商模型"""
147 name: Optional[str] = Field(None, min_length=1, max_length=100)
148 code: Optional[str] = Field(None, min_length=1, max_length=50)
149 type: Optional[BrokerType] = None
150 status: Optional[BrokerStatus] = None
151 config: Optional[BrokerConfig] = None
154class Broker(BrokerBase):
155 """券商模型"""
157 id: str = Field(..., description="券商ID")
158 created_at: datetime = Field(..., description="创建时间")
159 updated_at: datetime = Field(..., description="更新时间")
161 class Config:
162 from_attributes = True
165class BrokerResponse(Broker):
166 """券商响应模型(隐藏敏感信息)"""
168 config: Dict[str, Any] = Field(..., description="券商配置(脱敏)")
170 def model_post_init(self, __context) -> None:
171 """后处理,隐藏敏感信息"""
172 if self.config and "config" in self.config:
173 # 隐藏敏感信息
174 config_data = self.config["config"].copy()
175 sensitive_keys = [
176 "app_secret",
177 "access_token",
178 "secret",
179 "password",
180 "token",
181 ]
182 for key in sensitive_keys:
183 if key in config_data:
184 config_data[key] = "***"
185 self.config["config"] = config_data
188class DataSourceStatus(str, Enum):
189 """数据源状态枚举"""
191 ACTIVE = "active"
192 INACTIVE = "inactive"
195class DataSourceType(str, Enum):
196 """数据源类型枚举"""
198 LONGPORT = "longport"
199 OTHER = "other"
202class DataSourceBase(BaseModel):
203 """数据源基础模型"""
205 name: str = Field(..., min_length=1, max_length=100, description="数据源名称")
206 type: DataSourceType = Field(..., description="数据源类型")
207 broker_id: str = Field(..., description="关联券商ID")
208 status: DataSourceStatus = Field(DataSourceStatus.ACTIVE, description="状态")
209 priority: int = Field(1, ge=1, le=100, description="优先级")
212class DataSourceCreate(DataSourceBase):
213 """创建数据源模型"""
215 pass
218class DataSourceUpdate(BaseModel):
219 """更新数据源模型"""
221 name: Optional[str] = Field(None, min_length=1, max_length=100)
222 type: Optional[DataSourceType] = None
223 broker_id: Optional[str] = None
224 status: Optional[DataSourceStatus] = None
225 priority: Optional[int] = Field(None, ge=1, le=100)
228class DataSource(DataSourceBase):
229 """数据源模型"""
231 id: str = Field(..., description="数据源ID")
232 created_at: datetime = Field(..., description="创建时间")
233 updated_at: datetime = Field(..., description="更新时间")
235 class Config:
236 from_attributes = True
239class BrokerTestRequest(BaseModel):
240 """券商测试请求"""
242 broker_id: str = Field(..., description="券商ID")
245class DataSourceTestRequest(BaseModel):
246 """数据源测试请求"""
248 data_source_id: str = Field(..., description="数据源ID")
251class TestResponse(BaseModel):
252 """测试响应"""
254 success: bool = Field(..., description="测试结果")
255 message: str = Field(..., description="测试消息")
256 response_time: Optional[float] = Field(None, description="响应时间(毫秒)")
259class TradingFee(BaseModel):
260 """交易费用明细"""
262 platform_fee: Decimal = Field(default=Decimal("0"), description="平台费")
263 activity_fee: Decimal = Field(default=Decimal("0"), description="交易活动费")
264 clearing_fee: Decimal = Field(default=Decimal("0"), description="交收费")
265 audit_fee: Decimal = Field(default=Decimal("0"), description="综合审计费")
266 total_fee: Decimal = Field(default=Decimal("0"), description="总费用")
267 currency: str = Field(default="USD", description="币种(USD/HKD)")
268 calculation_details: Dict[str, Any] = Field(
269 default_factory=dict, description="计算详情"
270 )
273class FeeCalculateRequest(BaseModel):
274 """费用计算请求"""
276 broker_id: str = Field(..., description="券商ID")
277 quantity: Decimal = Field(..., gt=0, description="成交数量")
278 price: Decimal = Field(..., gt=0, description="成交价格")
279 side: str = Field(..., description="买卖方向(buy/sell)")
280 market: str = Field(..., description="市场类型(US/HK)")
283class FeeCalculateResponse(BaseModel):
284 """费用计算响应"""
286 fee_details: TradingFee = Field(..., description="费用明细")
287 trade_amount: Decimal = Field(..., description="交易金额")
288 total_cost: Decimal = Field(..., description="总成本(交易金额+费用)")