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

1""" 

2券商数据模型 

3""" 

4 

5from datetime import datetime 

6from decimal import Decimal 

7from enum import Enum 

8from typing import Any, Dict, Optional 

9 

10from pydantic import BaseModel, Field 

11 

12 

13class BrokerType(str, Enum): 

14 """券商类型枚举""" 

15 

16 LONGPORT = "longport" 

17 OTHER = "other" 

18 

19 

20class BrokerStatus(str, Enum): 

21 """券商状态枚举""" 

22 

23 ACTIVE = "active" 

24 INACTIVE = "inactive" 

25 

26 

27class LanguageType(str, Enum): 

28 """语言类型枚举""" 

29 

30 ZH_CN = "zh-CN" 

31 ZH_HK = "zh-HK" 

32 EN = "en" 

33 

34 

35class USFeeConfig(BaseModel): 

36 """美股交易费用配置""" 

37 

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 ) 

45 

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 ) 

53 

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 ) 

61 

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 ) 

69 

70 

71class HKFeeConfig(BaseModel): 

72 """港股交易费用配置""" 

73 

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 ) 

81 

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 ) 

89 

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 ) 

97 

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 ) 

105 

106 

107class FeeConfig(BaseModel): 

108 """交易费用配置""" 

109 

110 us_fees: USFeeConfig = Field( 

111 default_factory=USFeeConfig, description="美股费用配置" 

112 ) 

113 hk_fees: HKFeeConfig = Field( 

114 default_factory=HKFeeConfig, description="港股费用配置" 

115 ) 

116 

117 

118class BrokerConfig(BaseModel): 

119 """券商配置(通用JSON配置)""" 

120 

121 config: dict = Field(..., description="券商配置JSON") 

122 fee_config: Optional[FeeConfig] = Field( 

123 default_factory=FeeConfig, description="交易费用配置" 

124 ) 

125 

126 

127class BrokerBase(BaseModel): 

128 """券商基础模型""" 

129 

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") 

136 

137 

138class BrokerCreate(BrokerBase): 

139 """创建券商模型""" 

140 

141 pass 

142 

143 

144class BrokerUpdate(BaseModel): 

145 """更新券商模型""" 

146 

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 

152 

153 

154class Broker(BrokerBase): 

155 """券商模型""" 

156 

157 id: str = Field(..., description="券商ID") 

158 created_at: datetime = Field(..., description="创建时间") 

159 updated_at: datetime = Field(..., description="更新时间") 

160 

161 class Config: 

162 from_attributes = True 

163 

164 

165class BrokerResponse(Broker): 

166 """券商响应模型(隐藏敏感信息)""" 

167 

168 config: Dict[str, Any] = Field(..., description="券商配置(脱敏)") 

169 

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 

186 

187 

188class DataSourceStatus(str, Enum): 

189 """数据源状态枚举""" 

190 

191 ACTIVE = "active" 

192 INACTIVE = "inactive" 

193 

194 

195class DataSourceType(str, Enum): 

196 """数据源类型枚举""" 

197 

198 LONGPORT = "longport" 

199 OTHER = "other" 

200 

201 

202class DataSourceBase(BaseModel): 

203 """数据源基础模型""" 

204 

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="优先级") 

210 

211 

212class DataSourceCreate(DataSourceBase): 

213 """创建数据源模型""" 

214 

215 pass 

216 

217 

218class DataSourceUpdate(BaseModel): 

219 """更新数据源模型""" 

220 

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) 

226 

227 

228class DataSource(DataSourceBase): 

229 """数据源模型""" 

230 

231 id: str = Field(..., description="数据源ID") 

232 created_at: datetime = Field(..., description="创建时间") 

233 updated_at: datetime = Field(..., description="更新时间") 

234 

235 class Config: 

236 from_attributes = True 

237 

238 

239class BrokerTestRequest(BaseModel): 

240 """券商测试请求""" 

241 

242 broker_id: str = Field(..., description="券商ID") 

243 

244 

245class DataSourceTestRequest(BaseModel): 

246 """数据源测试请求""" 

247 

248 data_source_id: str = Field(..., description="数据源ID") 

249 

250 

251class TestResponse(BaseModel): 

252 """测试响应""" 

253 

254 success: bool = Field(..., description="测试结果") 

255 message: str = Field(..., description="测试消息") 

256 response_time: Optional[float] = Field(None, description="响应时间(毫秒)") 

257 

258 

259class TradingFee(BaseModel): 

260 """交易费用明细""" 

261 

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 ) 

271 

272 

273class FeeCalculateRequest(BaseModel): 

274 """费用计算请求""" 

275 

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)") 

281 

282 

283class FeeCalculateResponse(BaseModel): 

284 """费用计算响应""" 

285 

286 fee_details: TradingFee = Field(..., description="费用明细") 

287 trade_amount: Decimal = Field(..., description="交易金额") 

288 total_cost: Decimal = Field(..., description="总成本(交易金额+费用)")