修改了bsp state,继续测试
This commit is contained in:
+74
-29
@@ -45,7 +45,7 @@ exchange = ccxt.binance({
|
||||
'enableRateLimit': True,
|
||||
})
|
||||
|
||||
# 初始化A股数据获取器
|
||||
# 初始化 A 股数据获取器(K 线优先请求 A-Share Data Platform,默认 http://103.179.242.166:8000 ,见 /api/v1/klines 文档;ASHARE_DP_URL 覆盖,置空则仅用 AKShare)
|
||||
china_stock = ChinaStockData()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -65,6 +65,7 @@ def _zone_cache_ttl(tf_name: str) -> int:
|
||||
else:
|
||||
return 1800 # 4h+: 30分钟
|
||||
|
||||
# 加密货币本地/自建行情服务(与 A 股 ASHARE_DP_URL 端口可不同)
|
||||
DATA_SERVICE_URL = os.environ.get("DATA_SERVICE_URL", os.environ.get("DATASVC_URL", "http://103.179.242.166"))
|
||||
|
||||
DEFAULT_TIMEFRAME_LABELS = OrderedDict([
|
||||
@@ -150,6 +151,40 @@ def build_timeframe_labels(timeframes):
|
||||
return labels
|
||||
|
||||
|
||||
def compute_timeframe_defaults(labels_ordered):
|
||||
"""
|
||||
根据已排序的「周期 → 中文标签」映射,计算主 / 次 / 次次周期默认值。
|
||||
labels_ordered: OrderedDict 或按插入顺序排列的 dict。
|
||||
"""
|
||||
if not labels_ordered:
|
||||
labels_ordered = DEFAULT_TIMEFRAME_LABELS.copy()
|
||||
timeframe_keys = list(labels_ordered.keys())
|
||||
preferred_main = next((tf for tf in ['5m', '15m', '1h'] if tf in labels_ordered), None)
|
||||
default_main = preferred_main or (timeframe_keys[0] if timeframe_keys else '1m')
|
||||
if default_main not in labels_ordered and timeframe_keys:
|
||||
default_main = timeframe_keys[0]
|
||||
|
||||
if timeframe_keys:
|
||||
try:
|
||||
idx = timeframe_keys.index(default_main)
|
||||
default_element = timeframe_keys[idx - 1] if idx > 0 else timeframe_keys[0]
|
||||
except ValueError:
|
||||
default_element = timeframe_keys[0]
|
||||
else:
|
||||
default_element = default_main
|
||||
|
||||
if timeframe_keys:
|
||||
try:
|
||||
idx_el = timeframe_keys.index(default_element)
|
||||
default_sub_sub = timeframe_keys[idx_el - 1] if idx_el > 0 else timeframe_keys[0]
|
||||
except ValueError:
|
||||
default_sub_sub = timeframe_keys[0]
|
||||
else:
|
||||
default_sub_sub = default_element
|
||||
|
||||
return default_main, default_element, default_sub_sub, timeframe_keys
|
||||
|
||||
|
||||
def _parse_time_input(value):
|
||||
if value in (None, '', 0):
|
||||
return None
|
||||
@@ -230,7 +265,8 @@ def _fetch_kl_from_datasvc(symbol, timeframe, start_ms=None, end_ms=None, limit=
|
||||
refresh_data_service_metadata(force=True)
|
||||
|
||||
# A股热门股票
|
||||
A_STOCK_SYMBOLS = china_stock.get_popular_stocks()
|
||||
# 模板中 A 股下拉仅放默认一项;用户切换到「A股」时由前端请求 /api/a_stocks 填充全市场(约 5500+)
|
||||
A_STOCK_SYMBOLS = [{'symbol': '000001', 'name': '平安银行'}]
|
||||
|
||||
def detect_symbol_type(symbol):
|
||||
"""检测交易对类型:crypto 或 a_stock"""
|
||||
@@ -1226,39 +1262,15 @@ def serve_charting_library(filename):
|
||||
def index():
|
||||
"""主页"""
|
||||
refresh_data_service_metadata()
|
||||
timeframe_items = list(TIMEFRAMES.items())
|
||||
timeframe_keys = [item[0] for item in timeframe_items]
|
||||
tf_map = TIMEFRAMES if TIMEFRAMES else DEFAULT_TIMEFRAME_LABELS.copy()
|
||||
default_main, default_element, default_sub_sub, timeframe_keys = compute_timeframe_defaults(OrderedDict(tf_map))
|
||||
symbols = SYMBOLS if SYMBOLS else DEFAULT_SYMBOLS
|
||||
|
||||
preferred_main = next((tf for tf in ['5m', '15m', '1h'] if tf in TIMEFRAMES), None)
|
||||
default_main = preferred_main or (timeframe_keys[0] if timeframe_keys else '1m')
|
||||
if default_main not in TIMEFRAMES and timeframe_keys:
|
||||
default_main = timeframe_keys[0]
|
||||
|
||||
if timeframe_keys:
|
||||
try:
|
||||
idx = timeframe_keys.index(default_main)
|
||||
default_element = timeframe_keys[idx - 1] if idx > 0 else timeframe_keys[0]
|
||||
except ValueError:
|
||||
default_element = timeframe_keys[0]
|
||||
else:
|
||||
default_element = default_main
|
||||
|
||||
# 次次周期默认比次周期小一档
|
||||
if timeframe_keys:
|
||||
try:
|
||||
idx_el = timeframe_keys.index(default_element)
|
||||
default_sub_sub = timeframe_keys[idx_el - 1] if idx_el > 0 else timeframe_keys[0]
|
||||
except ValueError:
|
||||
default_sub_sub = timeframe_keys[0]
|
||||
else:
|
||||
default_sub_sub = default_element
|
||||
|
||||
default_symbol = 'BTC/USDT:USDT' if 'BTC/USDT:USDT' in symbols else (symbols[0] if symbols else '')
|
||||
|
||||
return render_template(
|
||||
'index.html',
|
||||
timeframes=TIMEFRAMES,
|
||||
timeframes=tf_map,
|
||||
symbols=symbols,
|
||||
a_stock_symbols=A_STOCK_SYMBOLS,
|
||||
default_main_timeframe=default_main,
|
||||
@@ -1269,6 +1281,39 @@ def index():
|
||||
data_service_available=DATA_SERVICE_AVAILABLE,
|
||||
)
|
||||
|
||||
|
||||
@app.route('/api/chart_metadata')
|
||||
def api_chart_metadata():
|
||||
"""
|
||||
按数据源返回图表用 K 线周期(中文标签)及主/次/次次默认周期。
|
||||
crypto:强制刷新 DATA_SERVICE_URL /health 元信息;
|
||||
a_stock:读取 ASHARE_DP_URL 的 /api/v1/klines/available-freqs,不修改全局加密货币 TIMEFRAMES。
|
||||
"""
|
||||
source = (request.args.get('source') or 'crypto').strip().lower()
|
||||
if source not in ('crypto', 'a_stock'):
|
||||
source = 'crypto'
|
||||
try:
|
||||
if source == 'a_stock':
|
||||
raw = china_stock.get_available_kline_freqs()
|
||||
labels_od = build_timeframe_labels(raw)
|
||||
else:
|
||||
refresh_data_service_metadata(force=True)
|
||||
labels_od = OrderedDict(TIMEFRAMES if TIMEFRAMES else DEFAULT_TIMEFRAME_LABELS.copy())
|
||||
|
||||
default_main, default_element, default_sub_sub, keys = compute_timeframe_defaults(labels_od)
|
||||
return jsonify({
|
||||
'source': source,
|
||||
'timeframes': {k: v for k, v in labels_od.items()},
|
||||
'timeframe_keys': keys,
|
||||
'default_main': default_main,
|
||||
'default_element': default_element,
|
||||
'default_sub_sub': default_sub_sub,
|
||||
})
|
||||
except Exception as exc:
|
||||
logger.exception('chart_metadata 失败: %s', exc)
|
||||
return jsonify({'error': str(exc)}), 500
|
||||
|
||||
|
||||
@app.route('/api/analyze')
|
||||
def analyze():
|
||||
"""分析接口"""
|
||||
|
||||
Reference in New Issue
Block a user