新增行情K线页,支持分时与多周期图表
扩展新浪K线拉取与合成逻辑,提供 ECharts 交互图表及实时报价 API。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,7 +30,7 @@ from fee_specs import (
|
||||
from fee_sync import sync_fees_from_akshare
|
||||
from contract_profile import get_contract_profile
|
||||
from stats_engine import STATS_VIEWS, load_stats_cache, refresh_stats_cache
|
||||
from kline_chart import generate_review_kline_chart
|
||||
from kline_chart import generate_review_kline_chart, fetch_market_klines, MARKET_PERIODS
|
||||
from market import get_price as market_get_price, set_ths_refresh_token, get_quote_source_label
|
||||
|
||||
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
|
||||
@@ -1297,6 +1297,66 @@ def api_stats_refresh():
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
@app.route("/market")
|
||||
@login_required
|
||||
def market_page():
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
period = request.args.get("period", "15m").strip()
|
||||
valid = {p["key"] for p in MARKET_PERIODS}
|
||||
if period not in valid:
|
||||
period = "15m"
|
||||
return render_template(
|
||||
"market.html",
|
||||
symbol=symbol,
|
||||
period=period,
|
||||
market_periods=MARKET_PERIODS,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/api/kline")
|
||||
@login_required
|
||||
def api_kline():
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
period = request.args.get("period", "15m").strip()
|
||||
if not symbol:
|
||||
return jsonify({"error": "请提供合约代码"}), 400
|
||||
try:
|
||||
data = fetch_market_klines(symbol, period)
|
||||
except Exception as exc:
|
||||
app.logger.warning("kline api failed: %s", exc)
|
||||
return jsonify({"error": str(exc)}), 500
|
||||
if not data.get("chart_symbol"):
|
||||
return jsonify({"error": "无法识别合约代码"}), 400
|
||||
if not data.get("bars"):
|
||||
return jsonify({"error": "未获取到K线数据,请稍后重试或更换合约"}), 404
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
@app.route("/api/market_quote")
|
||||
@login_required
|
||||
def api_market_quote():
|
||||
symbol = request.args.get("symbol", "").strip()
|
||||
market_code = request.args.get("market_code", "").strip()
|
||||
sina_code = request.args.get("sina_code", "").strip()
|
||||
if not symbol and not market_code:
|
||||
return jsonify({"error": "请提供合约"}), 400
|
||||
if not market_code or not sina_code:
|
||||
codes = ths_to_codes(symbol)
|
||||
if codes:
|
||||
market_code = codes.get("market_code", "") or market_code
|
||||
sina_code = codes.get("sina_code", "") or sina_code
|
||||
price = market_get_price(market_code, sina_code)
|
||||
name = symbol
|
||||
codes = ths_to_codes(symbol)
|
||||
if codes:
|
||||
name = codes.get("name", symbol)
|
||||
return jsonify({
|
||||
"symbol": symbol,
|
||||
"name": name,
|
||||
"price": price,
|
||||
})
|
||||
|
||||
|
||||
@app.route("/contract")
|
||||
@login_required
|
||||
def contract_profile_page():
|
||||
|
||||
Reference in New Issue
Block a user