fix: 修复外部因素数据源 - 北向资金改为南向资金,修复P0-P7全部外部因素
- P0资金面:DB数据过期时用麦蕊API获取资金流向 - P1市场情绪:去掉turnover字段依赖(DB无此字段) - P2南向资金:北向实时数据已停公布,改用南向资金(港股通)替代 - P3美股:用腾讯财经API替代失效的AKShare接口 - P4大宗商品:用腾讯财经API替代,修复var_name解析 - P7汇率:用新浪财经API替代失效的AKShare接口 - 修复评分详情API技术得分硬编码问题 - 前端传入tech_score参数确保明细与列表分数一致
This commit is contained in:
@@ -73,10 +73,105 @@ def get_fund_flow_history(stock_code, days=10):
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def _get_fund_flow_from_mairui(stock_code, days=10):
|
||||
"""从麦蕊智数API获取资金流向数据,转换为与DB记录相同的格式。
|
||||
|
||||
API: https://api.mairuiapi.com/hsstock/history/transaction/{code}/{licence}?lt={n}
|
||||
字段: zmbtdcje=主买特大单, zmbddcje=主买大单, zmbzdcje=主买中单, zmbxdcje=主买小单
|
||||
zmstdcje=主卖特大单, zmsddcje=主卖大单, zmszdcje=主卖中单, zmsxdcje=主卖小单
|
||||
"""
|
||||
try:
|
||||
import requests
|
||||
from config import Config
|
||||
LICENCE = Config.MAIRUI_LICENCE or "5352ED2F-94E5-4E96-8B7F-B57BA75284E3"
|
||||
url = f"https://api.mairuiapi.com/hsstock/history/transaction/{stock_code}/{LICENCE}?lt={days}"
|
||||
resp = requests.get(url, timeout=10)
|
||||
if resp.status_code != 200:
|
||||
logger.warning(f"麦蕊资金流向API返回{resp.status_code}")
|
||||
return []
|
||||
|
||||
data = resp.json()
|
||||
if not data or not isinstance(data, list):
|
||||
return []
|
||||
|
||||
records = []
|
||||
for item in data:
|
||||
# 主买总额 = 特大单+大单+中单+小单
|
||||
buy_total = (
|
||||
float(item.get('zmbtdcje', 0) or 0) +
|
||||
float(item.get('zmbddcje', 0) or 0) +
|
||||
float(item.get('zmbzdcje', 0) or 0) +
|
||||
float(item.get('zmbxdcje', 0) or 0)
|
||||
)
|
||||
# 主卖总额
|
||||
sell_total = (
|
||||
float(item.get('zmstdcje', 0) or 0) +
|
||||
float(item.get('zmsddcje', 0) or 0) +
|
||||
float(item.get('zmszdcje', 0) or 0) +
|
||||
float(item.get('zmsxdcje', 0) or 0)
|
||||
)
|
||||
# 主力净流入 = (特大单+大单)买 - (特大单+大单)卖
|
||||
main_buy = float(item.get('zmbtdcje', 0) or 0) + float(item.get('zmbddcje', 0) or 0)
|
||||
main_sell = float(item.get('zmstdcje', 0) or 0) + float(item.get('zmsddcje', 0) or 0)
|
||||
main_net = main_buy - main_sell
|
||||
|
||||
# 超大单净流入
|
||||
super_net = float(item.get('zmbtdcje', 0) or 0) - float(item.get('zmstdcje', 0) or 0)
|
||||
|
||||
# 总成交额
|
||||
total_amount = buy_total + sell_total
|
||||
main_net_pct = round(main_net / total_amount * 100, 2) if total_amount > 0 else 0
|
||||
super_net_pct = round(super_net / total_amount * 100, 2) if total_amount > 0 else 0
|
||||
|
||||
# 大单净流入
|
||||
big_net = float(item.get('zmbddcje', 0) or 0) - float(item.get('zmsddcje', 0) or 0)
|
||||
big_net_pct = round(big_net / total_amount * 100, 2) if total_amount > 0 else 0
|
||||
|
||||
# 中单净流入
|
||||
mid_net = float(item.get('zmbzdcje', 0) or 0) - float(item.get('zmszdcje', 0) or 0)
|
||||
mid_net_pct = round(mid_net / total_amount * 100, 2) if total_amount > 0 else 0
|
||||
|
||||
# 小单净流入
|
||||
small_net = float(item.get('zmbxdcje', 0) or 0) - float(item.get('zmsxdcje', 0) or 0)
|
||||
small_net_pct = round(small_net / total_amount * 100, 2) if total_amount > 0 else 0
|
||||
|
||||
# 日期解析
|
||||
t_str = str(item.get('t', ''))
|
||||
date_str = t_str[:10] if t_str else ''
|
||||
|
||||
records.append({
|
||||
'date': date_str,
|
||||
'close_price': 0,
|
||||
'change_pct': 0,
|
||||
'main_net_inflow': round(main_net, 2),
|
||||
'main_net_inflow_pct': main_net_pct,
|
||||
'super_net_inflow': round(super_net, 2),
|
||||
'super_net_inflow_pct': super_net_pct,
|
||||
'big_net_inflow': round(big_net, 2),
|
||||
'big_net_inflow_pct': big_net_pct,
|
||||
'mid_net_inflow': round(mid_net, 2),
|
||||
'mid_net_inflow_pct': mid_net_pct,
|
||||
'small_net_inflow': round(small_net, 2),
|
||||
'small_net_inflow_pct': small_net_pct,
|
||||
})
|
||||
|
||||
# 按日期升序排列
|
||||
records.sort(key=lambda x: x['date'])
|
||||
logger.info(f"麦蕊API获取{stock_code}资金流向{len(records)}条")
|
||||
return records
|
||||
except Exception as e:
|
||||
logger.warning(f"麦蕊资金流向API失败({stock_code}): {e}")
|
||||
return []
|
||||
|
||||
|
||||
def analyze_fund_flow(stock_code, days=5):
|
||||
"""
|
||||
分析主力资金流向,返回资金面评分和信号
|
||||
|
||||
数据源优先级:
|
||||
1. DB stock_fund_flow_history 表(有最新数据时)
|
||||
2. 麦蕊智数API hsstock/history/transaction(DB数据过期时补充)
|
||||
|
||||
参数:
|
||||
stock_code: 股票代码
|
||||
days: 分析最近几天的资金流向
|
||||
@@ -91,6 +186,28 @@ def analyze_fund_flow(stock_code, days=5):
|
||||
}
|
||||
"""
|
||||
records = get_fund_flow_history(stock_code, days=days + 5)
|
||||
|
||||
# 检查DB数据是否足够新(最近3天内有数据)
|
||||
use_mairui = False
|
||||
if len(records) < 2:
|
||||
use_mairui = True
|
||||
else:
|
||||
from datetime import date
|
||||
latest_date = records[-1].get('date', '')
|
||||
if latest_date:
|
||||
try:
|
||||
latest = datetime.strptime(latest_date, '%Y-%m-%d').date()
|
||||
if (date.today() - latest).days > 5:
|
||||
use_mairui = True
|
||||
except ValueError:
|
||||
use_mairui = True
|
||||
|
||||
if use_mairui:
|
||||
# 用麦蕊API获取资金流向数据
|
||||
mairui_records = _get_fund_flow_from_mairui(stock_code, days + 5)
|
||||
if mairui_records:
|
||||
records = mairui_records
|
||||
|
||||
if len(records) < 2:
|
||||
return {
|
||||
'score': 0,
|
||||
|
||||
Reference in New Issue
Block a user