fix: 股票的一键检测、一键缓存完成(缓存需要优化进度)

master
Lxy 2 months ago
parent 660f5ebc20
commit b54a0cee58

@ -35,7 +35,8 @@ async def detect_all_missing_data(
request.security_type,
request.period_type,
start,
end
end,
request.contract_type
)
return ResponseModel(data=result)
@ -56,7 +57,8 @@ async def cache_all_missing_data(
request.security_type,
request.period_type,
start,
end
end,
request.contract_type
)
return ResponseModel(data={
@ -215,4 +217,33 @@ async def get_cache_status(
return ResponseModel(data=status)
@router.get("/future-varieties", response_model=ResponseModel)
async def get_future_varieties(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取期货品种列表"""
service = CacheService(db)
varieties = service.get_future_varieties()
return ResponseModel(data={"varieties": varieties})
@router.get("/main-contracts", response_model=ResponseModel)
async def get_main_contracts(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取所有品种的主力合约"""
from app.services.sdk_manager import sdk_manager
adapter = sdk_manager.get_default_connection()
if not adapter:
return ResponseModel(code=500, message="SDK连接失败")
main_contracts = adapter.get_all_main_contracts()
return ResponseModel(data={"main_contracts": main_contracts})
from app.utils.date_utils import format_date

@ -114,3 +114,4 @@ class AllDataRequest(BaseModel):
period_type: str = Field(default="daily", description="周期类型: daily, min1, min5, etc.")
start_date: str = Field(..., description="开始日期 YYYYMMDD")
end_date: str = Field(..., description="结束日期 YYYYMMDD")
contract_type: str = Field(default="all", description="合约类型: all, main - 仅对期货有效")

@ -113,11 +113,120 @@ class AmazingDataAdapter:
raise RuntimeError("SDK未连接")
try:
return self._base_data.get_code_list(security_type)
if security_type == "EXTRA_FUTURE":
return self._base_data.get_future_code_list()
elif security_type == "EXTRA_OPTION":
return self._base_data.get_option_code_list()
else:
return self._base_data.get_code_list(security_type)
except Exception as e:
logger.error(f"获取代码列表失败: {str(e)}")
return []
def get_future_varieties(self) -> List[str]:
"""
获取期货品种列表
Returns:
品种代码列表 (: IF, IC, al, zn, etc.)
"""
if not self._is_connected:
raise RuntimeError("SDK未连接")
try:
codes = self._base_data.get_future_code_list()
varieties = set()
for code in codes:
# 代码格式: 品种代码+月份+交易所
# 如: IF2401.CFE, al2702.SHF
parts = code.split('.')
if len(parts) >= 1:
contract = parts[0]
# 提取品种代码(去掉月份部分)
# 月份格式: YYMM (如 2401, 2702)
variety = contract[:-4] if len(contract) > 4 else contract
varieties.add(variety)
return sorted(list(varieties))
except Exception as e:
logger.error(f"获取期货品种列表失败: {str(e)}")
return []
def get_main_contract(self, variety: str) -> Optional[str]:
"""
获取指定品种的当前主力合约
Args:
variety: 品种代码 (: IF, IC, al, zn)
Returns:
主力合约代码 (: IF2401.CFE)
"""
if not self._is_connected:
raise RuntimeError("SDK未连接")
try:
from datetime import datetime
codes = self._base_data.get_future_code_list()
current_year = datetime.now().year
current_month = datetime.now().month
# 筛选该品种的合约
variety_codes = []
for code in codes:
parts = code.split('.')
if len(parts) >= 1:
contract = parts[0]
if contract.startswith(variety) and len(contract) > len(variety):
variety_codes.append(code)
if not variety_codes:
return None
# 找到最近月份的合约作为主力合约
# 主力合约通常是当前月份或下个月份的合约
def get_contract_month(code):
parts = code.split('.')
contract = parts[0]
month_str = contract[-4:] # YYMM
try:
year = int(month_str[:2]) + 2000
month = int(month_str[2:])
return (year, month)
except:
return (9999, 99)
# 按月份排序
variety_codes.sort(key=get_contract_month)
# 找到第一个大于当前月份的合约
for code in variety_codes:
year, month = get_contract_month(code)
if year >= current_year and month >= current_month:
return code
# 如果没有找到,返回最后一个合约
return variety_codes[-1] if variety_codes else None
except Exception as e:
logger.error(f"获取主力合约失败: {str(e)}")
return None
def get_all_main_contracts(self) -> Dict[str, str]:
"""
获取所有品种的主力合约
Returns:
字典 {品种: 主力合约}
"""
varieties = self.get_future_varieties()
main_contracts = {}
for variety in varieties:
main_contract = self.get_main_contract(variety)
if main_contract:
main_contracts[variety] = main_contract
return main_contracts
def get_code_info(self, security_type: str) -> pd.DataFrame:
"""
获取证券信息

@ -29,12 +29,13 @@ class CacheService:
self.stock_service = StockService(db)
self.future_service = FutureService(db)
def get_all_codes(self, security_type: str) -> List[str]:
def get_all_codes(self, security_type: str, contract_type: str = "all") -> List[str]:
"""
获取所有代码列表
Args:
security_type: 证券类型 (stock, future)
contract_type: 合约类型 (all, main) - 仅对期货有效
Returns:
代码列表
@ -46,16 +47,29 @@ class CacheService:
if security_type == "stock":
return adapter.get_code_list("EXTRA_STOCK_A")
elif security_type == "future":
return adapter.get_code_list("EXTRA_FUTURE")
if contract_type == "main":
# 只获取主力合约
main_contracts = adapter.get_all_main_contracts()
return list(main_contracts.values())
else:
return adapter.get_code_list("EXTRA_FUTURE")
else:
return []
def get_future_varieties(self) -> List[str]:
"""获取期货品种列表"""
adapter = sdk_manager.get_default_connection()
if not adapter:
raise RuntimeError("SDK连接失败")
return adapter.get_future_varieties()
def detect_all_missing_data(
self,
security_type: str,
period_type: str,
start_date: date,
end_date: date
end_date: date,
contract_type: str = "all"
) -> Dict:
"""
一键检测所有数据的缺失情况
@ -65,12 +79,13 @@ class CacheService:
period_type: 周期类型 (daily, min1, etc.)
start_date: 开始日期
end_date: 结束日期
contract_type: 合约类型 (all, main) - 仅对期货有效
Returns:
检测结果字典
"""
# 获取所有代码
code_list = self.get_all_codes(security_type)
code_list = self.get_all_codes(security_type, contract_type)
if not code_list:
raise ValueError(f"无法获取{security_type}代码列表")
@ -79,7 +94,7 @@ class CacheService:
# 创建检测任务
task = CacheTask(
task_name=f"一键检测所有数据 - {security_type} - {len(code_list)}个代码",
task_name=f"一键检测所有数据 - {security_type} - {contract_type} - {len(code_list)}个代码",
task_type="detect_all_missing",
security_type=security_type,
period_type=period_type,
@ -244,7 +259,8 @@ class CacheService:
security_type: str,
period_type: str,
start_date: date,
end_date: date
end_date: date,
contract_type: str = "all"
) -> CacheTask:
"""
一键缓存所有缺失数据
@ -254,12 +270,13 @@ class CacheService:
period_type: 周期类型
start_date: 开始日期
end_date: 结束日期
contract_type: 合约类型 (all, main) - 仅对期货有效
Returns:
缓存任务对象
"""
# 获取所有代码
code_list = self.get_all_codes(security_type)
code_list = self.get_all_codes(security_type, contract_type)
if not code_list:
raise ValueError(f"无法获取{security_type}代码列表")

@ -23,6 +23,7 @@ export const batchCacheData = (data: {
export const detectAllMissingData = (data: {
security_type: string
period_type: string
contract_type?: string
start_date: string
end_date: string
}) => {
@ -32,6 +33,7 @@ export const detectAllMissingData = (data: {
export const cacheAllMissingData = (data: {
security_type: string
period_type: string
contract_type?: string
start_date: string
end_date: string
}) => {
@ -56,3 +58,11 @@ export const getCacheStatus = (
) => {
return request.get(`/cache/status/${code}`, { params })
}
export const getFutureVarieties = () => {
return request.get('/cache/future-varieties')
}
export const getMainContracts = () => {
return request.get('/cache/main-contracts')
}

@ -8,6 +8,12 @@
<el-radio-button label="future">期货</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="合约类型" v-if="form.securityType === 'future'">
<el-radio-group v-model="form.contractType">
<el-radio-button label="all">所有合约</el-radio-button>
<el-radio-button label="main">主力合约</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="周期">
<el-select v-model="form.periodType" style="width: 120px;">
<el-option label="日线" value="daily" />
@ -222,6 +228,7 @@ const dailyStatsList = computed(() => {
const form = reactive({
securityType: 'stock',
periodType: 'daily',
contractType: 'all',
startDate: getDefaultStartDate(),
endDate: getDefaultEndDate()
})
@ -260,6 +267,7 @@ const handleDetectAll = async () => {
const res: any = await detectAllMissingData({
security_type: form.securityType,
period_type: form.periodType,
contract_type: form.contractType,
start_date: form.startDate,
end_date: form.endDate
})
@ -286,6 +294,7 @@ const handleCacheAll = async () => {
const res: any = await cacheAllMissingData({
security_type: form.securityType,
period_type: form.periodType,
contract_type: form.contractType,
start_date: form.startDate,
end_date: form.endDate
})

Loading…
Cancel
Save