1
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""测试 akshare 各函数能获取多少 PVC 5分钟历史数据。"""
|
||||
import akshare as ak
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
|
||||
print(f"akshare version: {ak.__version__}")
|
||||
print()
|
||||
|
||||
# 方法1: futures_zh_minute_sina - 新浪连续合约
|
||||
print("=== 方法1: futures_zh_minute_sina(V0, 5min) ===")
|
||||
try:
|
||||
df1 = ak.futures_zh_minute_sina(symbol="V0", period="5")
|
||||
print(f"行数: {len(df1)}")
|
||||
print(f"列: {list(df1.columns)}")
|
||||
if len(df1) > 0:
|
||||
print(f"时间范围: {df1.iloc[0,0]} ~ {df1.iloc[-1,0]}")
|
||||
print(df1.head(2))
|
||||
print(df1.tail(2))
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
|
||||
print()
|
||||
|
||||
# 方法2: 尝试下载多个具体合约拼接
|
||||
print("=== 方法2: 下载多个 PVC 合约 ===")
|
||||
all_dfs = []
|
||||
# PVC合约代码: V+YYMM, 如 V2401=2024年1月
|
||||
contracts = []
|
||||
for year in [23, 24, 25, 26]:
|
||||
for month in range(1, 13):
|
||||
code = f"V{year:02d}{month:02d}"
|
||||
contracts.append(code)
|
||||
|
||||
for code in contracts:
|
||||
try:
|
||||
df = ak.futures_zh_minute_sina(symbol=code, period="5")
|
||||
if df is not None and len(df) > 0:
|
||||
print(f" {code}: {len(df)} 行, {df.iloc[0,0]} ~ {df.iloc[-1,0]}")
|
||||
all_dfs.append(df)
|
||||
except Exception as e:
|
||||
pass # 合约可能已过期,跳过
|
||||
|
||||
print(f"\n总计获取 {len(all_dfs)} 个合约, 合计 {sum(len(d) for d in all_dfs)} 行")
|
||||
@@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""验证 tqsdk 账户能否登录并获取行情数据"""
|
||||
from tqsdk import TqApi, TqAuth
|
||||
import sys, time
|
||||
|
||||
USER = "七斗居士"
|
||||
PASSWORD = "ghhkphs8"
|
||||
|
||||
print(f"正在登录 tqsdk: {USER}")
|
||||
try:
|
||||
api = TqApi(auth=TqAuth(USER, PASSWORD))
|
||||
print("[OK] 登录成功!")
|
||||
|
||||
# 获取行情
|
||||
quote = api.get_quote("SHFE.cu2509")
|
||||
# 等待数据到达
|
||||
while quote.datetime == "":
|
||||
api.wait_update()
|
||||
|
||||
print(f"合约代码: {quote.instrument_id}")
|
||||
print(f"最新价: {quote.last_price}")
|
||||
print(f"买一价: {quote.bid_price1}")
|
||||
print(f"卖一价: {quote.ask_price1}")
|
||||
print(f"开盘价: {quote.open}")
|
||||
print(f"最高价: {quote.high}")
|
||||
print(f"最低价: {quote.low}")
|
||||
print(f"更新时间: {quote.datetime}")
|
||||
print("\n[OK] 账户有效, 行情数据获取成功!")
|
||||
|
||||
api.close()
|
||||
except Exception as e:
|
||||
print(f"[FAIL] {type(e).__name__}: {e}")
|
||||
sys.exit(1)
|
||||
@@ -127,7 +127,20 @@ def inspect_parquet_file(path: str | Path) -> dict[str, Any]:
|
||||
f"数据不足: {bars} bars(至少需要 {Config.MIN_BARS})"
|
||||
)
|
||||
|
||||
years = round(bars / 6240, 2) if timeframe == "H1" else None
|
||||
# 从实际时间跨度计算年数(适用于所有周期,比固定公式更准确)
|
||||
years = None
|
||||
if "time" in df.columns and len(df) > 1:
|
||||
try:
|
||||
t_min = float(df["time"].min())
|
||||
t_max = float(df["time"].max())
|
||||
if t_max > t_min and t_max > 1_000_000_000: # 合法的 Unix 时间戳
|
||||
span_seconds = t_max - t_min
|
||||
years = round(span_seconds / (365.25 * 24 * 3600), 2)
|
||||
except Exception:
|
||||
pass
|
||||
# 回退:H1 用固定公式(6240 根/年,24h 市场)
|
||||
if years is None and timeframe == "H1":
|
||||
years = round(bars / 6240, 2)
|
||||
return {
|
||||
"data_file": str(p.resolve()),
|
||||
"filename": p.name,
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
"""下载 PVC 5分钟 K 线数据到桌面。
|
||||
|
||||
使用 tqsdk 拉取 PVC主连(KQ.m@DCE.v) 的 5 分钟 K 线,
|
||||
保存为项目兼容的 Parquet 格式(time/open/high/low/close/tick_volume)。
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 读取 tqsdk 凭证(优先 web_settings.json,未配置则用默认账号)
|
||||
settings_path = Path(__file__).parent / "web_settings.json"
|
||||
try:
|
||||
settings = json.loads(settings_path.read_text(encoding="utf-8"))
|
||||
user = str(settings.get("tqsdk_user", "")).strip()
|
||||
pwd = str(settings.get("tqsdk_password", "")).strip()
|
||||
except Exception:
|
||||
user, pwd = "", ""
|
||||
|
||||
# 内置默认账号
|
||||
if not user or not pwd:
|
||||
user, pwd = "七斗居士", "ghhkphs8"
|
||||
|
||||
print(f"tqsdk 账号: {user}")
|
||||
print("正在连接天勤量化...")
|
||||
|
||||
from tqsdk import TqApi, TqAuth, TqSim
|
||||
import pandas as pd
|
||||
|
||||
# PVC主连 → tqsdk 主连代码
|
||||
TQSDK_SYMBOL = "KQ.m@DCE.v"
|
||||
DURATION = 300 # 5分钟 = 300秒
|
||||
DATA_LENGTH = 8000 # 尽量多拉
|
||||
|
||||
api = None
|
||||
try:
|
||||
api = TqApi(TqSim(), auth=TqAuth(user, pwd), disable_print=True)
|
||||
print("连接成功,正在拉取 PVC 5分钟 K 线...")
|
||||
|
||||
# adj_type="F" 前复权,消除换月跳价
|
||||
df = api.get_kline_serial(
|
||||
TQSDK_SYMBOL, DURATION, data_length=DATA_LENGTH, adj_type="F"
|
||||
)
|
||||
print(f"拉取到 {len(df)} 根 K 线")
|
||||
finally:
|
||||
if api is not None:
|
||||
try:
|
||||
api.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if df is None or df.empty:
|
||||
print("ERROR: 未拉取到数据")
|
||||
sys.exit(1)
|
||||
|
||||
# 过滤无效行(volume=0 的非交易时段,或 datetime=0)
|
||||
df = df[df["datetime"] != 0].copy()
|
||||
df = df[df["volume"] > 0].copy()
|
||||
print(f"过滤后有效 K 线: {len(df)} 根")
|
||||
|
||||
# 转换为项目兼容格式
|
||||
# tqsdk datetime 是纳秒级 Unix 时间戳 → 转秒
|
||||
result = pd.DataFrame()
|
||||
result["time"] = (df["datetime"].astype("int64") // 1_000_000_000).astype("int64")
|
||||
result["open"] = df["open"].astype("float64")
|
||||
result["high"] = df["high"].astype("float64")
|
||||
result["low"] = df["low"].astype("float64")
|
||||
result["close"] = df["close"].astype("float64")
|
||||
result["tick_volume"] = df["volume"].astype("int64")
|
||||
|
||||
# 按时间升序排列
|
||||
result = result.sort_values("time").reset_index(drop=True)
|
||||
|
||||
# 去除可能重复的时间戳
|
||||
result = result.drop_duplicates(subset=["time"], keep="last").reset_index(drop=True)
|
||||
|
||||
# 输出目录
|
||||
out_dir = Path(r"C:\Users\14795\Desktop\国内期货K线数据")
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
out_file = out_dir / "PVC_5min.parquet"
|
||||
|
||||
# 保存为 Parquet
|
||||
result.to_parquet(out_file, index=False)
|
||||
print(f"\n已保存: {out_file}")
|
||||
print(f"总行数: {len(result)}")
|
||||
|
||||
# 显示数据概览
|
||||
print(f"\n=== 数据概览 ===")
|
||||
print(f"时间范围: {pd.to_datetime(result['time'].iloc[0], unit='s')} ~ {pd.to_datetime(result['time'].iloc[-1], unit='s')}")
|
||||
print(f"开盘价范围: {result['open'].min():.2f} ~ {result['open'].max():.2f}")
|
||||
print(f"收盘价范围: {result['close'].min():.2f} ~ {result['close'].max():.2f}")
|
||||
print(f"\n前 5 行:")
|
||||
print(result.head().to_string())
|
||||
print(f"\n后 5 行:")
|
||||
print(result.tail().to_string())
|
||||
print("\n下载完成!")
|
||||
@@ -0,0 +1,124 @@
|
||||
"""修复版:下载 PVC 全历史 5分钟 K 线数据(akshare 多合约拼接)。
|
||||
|
||||
修复 pandas 3.0 时间戳转换问题,使用显式时区处理。
|
||||
"""
|
||||
import akshare as ak
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
from datetime import timezone, timedelta
|
||||
import time
|
||||
import sys
|
||||
|
||||
print("=" * 60)
|
||||
print(" PVC 全历史 5分钟 K 线下载(akshare 多合约拼接·修复版)")
|
||||
print("=" * 60)
|
||||
|
||||
# 北京时间 UTC+8
|
||||
BJ_TZ = timezone(timedelta(hours=8))
|
||||
|
||||
# 生成所有 PVC 合约代码: V2101 ~ V2612
|
||||
contracts = []
|
||||
for year in range(21, 27):
|
||||
for month in range(1, 13):
|
||||
contracts.append(f"V{year:02d}{month:02d}")
|
||||
|
||||
print(f"待下载合约数: {len(contracts)} 个 (V2101 ~ V2612)")
|
||||
print()
|
||||
|
||||
# 下载所有合约
|
||||
all_data = []
|
||||
success = 0
|
||||
for i, code in enumerate(contracts):
|
||||
try:
|
||||
df = ak.futures_zh_minute_sina(symbol=code, period="5")
|
||||
if df is not None and len(df) > 0:
|
||||
df = df.copy()
|
||||
df["_contract"] = code
|
||||
all_data.append(df)
|
||||
success += 1
|
||||
if (i + 1) % 12 == 0 or i == len(contracts) - 1:
|
||||
print(f" 进度: {i+1}/{len(contracts)} | 成功: {success}")
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(0.15)
|
||||
|
||||
print(f"\n下载完成: 成功 {success} 个合约, 总行数 {sum(len(d) for d in all_data)}")
|
||||
|
||||
# 合并
|
||||
print("\n正在拼接主力合约序列...")
|
||||
combined = pd.concat(all_data, ignore_index=True)
|
||||
|
||||
# 修复时间戳转换:显式按北京时间处理
|
||||
def to_unix_seconds(dt_str):
|
||||
"""将 '2020-09-17 21:35:00' 转为 Unix 秒(按北京时间 UTC+8)。"""
|
||||
try:
|
||||
dt = pd.to_datetime(dt_str)
|
||||
# 显式设置时区为北京时间,再转 Unix 时间戳
|
||||
return int(dt.replace(tzinfo=BJ_TZ).timestamp())
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
combined["_ts"] = combined["datetime"].apply(to_unix_seconds)
|
||||
combined = combined[combined["_ts"] > 0].copy() # 过滤无效
|
||||
|
||||
# 按时间戳+成交量排序,去重时保留成交量最大的(近似主力合约)
|
||||
print("按成交量选择主力合约(去重)...")
|
||||
combined = combined.sort_values(["_ts", "volume"], ascending=[True, False])
|
||||
combined = combined.drop_duplicates(subset=["_ts"], keep="first")
|
||||
combined = combined.sort_values("_ts").reset_index(drop=True)
|
||||
|
||||
print(f"去重后行数: {len(combined):,}")
|
||||
|
||||
# 验证时间戳
|
||||
first_dt = pd.to_datetime(combined["datetime"].iloc[0])
|
||||
last_dt = pd.to_datetime(combined["datetime"].iloc[-1])
|
||||
print(f"时间范围: {first_dt} ~ {last_dt}")
|
||||
span_days = (last_dt - first_dt).days
|
||||
print(f"时间跨度: {span_days} 天(约 {span_days/365.25:.1f} 年)")
|
||||
|
||||
# 验证时间戳正确性
|
||||
print(f"首行 Unix 时间戳: {combined['_ts'].iloc[0]}")
|
||||
print(f"首行时间戳验证: {pd.to_datetime(combined['_ts'].iloc[0], unit='s', utc=True).tz_convert(BJ_TZ)}")
|
||||
|
||||
# 转换为项目兼容格式
|
||||
result = pd.DataFrame()
|
||||
result["time"] = combined["_ts"].astype("int64")
|
||||
result["open"] = combined["open"].astype("float64")
|
||||
result["high"] = combined["high"].astype("float64")
|
||||
result["low"] = combined["low"].astype("float64")
|
||||
result["close"] = combined["close"].astype("float64")
|
||||
result["tick_volume"] = combined["volume"].astype("int64")
|
||||
result = result.drop_duplicates(subset=["time"], keep="last").reset_index(drop=True)
|
||||
|
||||
# 保存
|
||||
out_dir = Path(r"C:\Users\14795\Desktop\国内期货K线数据")
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
out_file = out_dir / "PVC_5min.parquet"
|
||||
result.to_parquet(out_file, index=False)
|
||||
|
||||
# 统计
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f" 下载完成!")
|
||||
print(f"{'=' * 60}")
|
||||
print(f"保存路径: {out_file}")
|
||||
print(f"总行数: {len(result):,}")
|
||||
print(f"时间范围: {first_dt} ~ {last_dt}")
|
||||
print(f"时间跨度: {span_days} 天(约 {span_days/365.25:.1f} 年)")
|
||||
|
||||
print(f"\n价格统计:")
|
||||
print(f" 开盘价: {result['open'].min():.0f} ~ {result['open'].max():.0f}")
|
||||
print(f" 收盘价: {result['close'].min():.0f} ~ {result['close'].max():.0f}")
|
||||
print(f" 均价: {result['close'].mean():.0f}")
|
||||
|
||||
# 按年统计
|
||||
result["_dt"] = pd.to_datetime(result["time"], unit="s", utc=True).dt.tz_convert(BJ_TZ)
|
||||
result["_year"] = result["_dt"].dt.year
|
||||
yearly = result.groupby("_year").size()
|
||||
print(f"\n各年数据量:")
|
||||
for yr, cnt in yearly.items():
|
||||
print(f" {yr}年: {cnt:,} 根")
|
||||
|
||||
print(f"\n前 3 行:")
|
||||
print(result[["time","open","high","low","close","tick_volume"]].head(3).to_string())
|
||||
print(f"\n后 3 行:")
|
||||
print(result[["time","open","high","low","close","tick_volume"]].tail(3).to_string())
|
||||
+26
-41
@@ -1,53 +1,38 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0"
|
||||
|
||||
REM Prefer: python -m pip ... (avoids pip-shim GBK issues on Chinese Windows)
|
||||
set HOST=127.0.0.1
|
||||
set PORT=8765
|
||||
|
||||
REM Use system Python 3.13 (has all deps installed)
|
||||
set PYTHON=C:\Program Files\Python313\python.exe
|
||||
title AlphaMaster Web Server
|
||||
cd /d "C:\Alpha_master"
|
||||
|
||||
echo ============================================================
|
||||
echo AlphaMaster Web Console
|
||||
echo http://%HOST%:%PORT%
|
||||
echo AlphaMaster - Quant Factor Mining Center
|
||||
echo Web Console Launcher
|
||||
echo ============================================================
|
||||
echo.
|
||||
|
||||
echo [1/3] Releasing port %PORT% if occupied ...
|
||||
for /f "tokens=5" %%P in ('netstat -ano ^| findstr ":%PORT% " ^| findstr LISTENING') do (
|
||||
echo taskkill PID %%P
|
||||
taskkill /F /PID %%P >nul 2>&1
|
||||
REM Check if Python is available
|
||||
where python >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo [ERROR] Python is not found on PATH.
|
||||
echo Please install Python 3.11+ and add it to your system PATH.
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
timeout /t 1 /nobreak >nul
|
||||
|
||||
echo [2/3] Starting uvicorn ...
|
||||
start "AlphaMaster Server" "%PYTHON%" run_web.py --host %HOST% --port %PORT%
|
||||
echo [1/2] Starting web server on http://127.0.0.1:8765 ...
|
||||
echo The browser will open automatically in 3 seconds.
|
||||
echo.
|
||||
echo Press Ctrl+C in this window to stop the server.
|
||||
echo ============================================================
|
||||
echo.
|
||||
|
||||
echo [3/3] Warming up APIs (torch/fastapi first import can take ~6s) ...
|
||||
set /a TRIES=0
|
||||
:wait_ready
|
||||
set /a TRIES+=1
|
||||
if %TRIES% GTR 90 goto ready_fail
|
||||
timeout /t 1 /nobreak >nul
|
||||
"%PYTHON%" -c "import urllib.request; urllib.request.urlopen('http://%HOST%:%PORT%/api/overview', timeout=2).read(); urllib.request.urlopen('http://%HOST%:%PORT%/api/ai/providers', timeout=2).read(); urllib.request.urlopen('http://%HOST%:%PORT%/api/strategies', timeout=2).read()" 2>nul
|
||||
if errorlevel 1 goto wait_ready
|
||||
REM Open the browser after a 3-second delay (gives the server time to start)
|
||||
start "" cmd /c "ping 127.0.0.1 -n 4 >nul 2>&1 & start http://127.0.0.1:8765"
|
||||
|
||||
REM Start the web server (blocks until Ctrl+C)
|
||||
python run_web.py --host 127.0.0.1 --port 8765
|
||||
|
||||
echo.
|
||||
echo Ready. Opening browser ...
|
||||
start "" "http://%HOST%:%PORT%/"
|
||||
echo.
|
||||
echo Server window title: AlphaMaster Server
|
||||
echo Press any key to close this launcher (server keeps running)...
|
||||
pause >nul
|
||||
exit /b 0
|
||||
|
||||
:ready_fail
|
||||
echo.
|
||||
echo ERROR: server did not become ready within ~90s.
|
||||
echo Check the "AlphaMaster Server" window for import/dependency errors.
|
||||
echo Tip: python -m pip install -r requirements.txt
|
||||
echo.
|
||||
echo ============================================================
|
||||
echo Server has stopped.
|
||||
echo ============================================================
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""国内期货数据源(tqsdk 天勤量化,实时行情)。
|
||||
|
||||
通过 tqsdk 实时拉取国内期货主连 K 线,支持 60 个品种 × 4 个周期。
|
||||
账号配置在 web_settings.json 的 tqsdk_user / tqsdk_password 字段。
|
||||
通过 tqsdk 实时拉取国内期货主连 K 线,支持 60 个品种 × 5 个周期。
|
||||
账号优先从 web_settings.json 读取,未配置时使用内置默认账号。
|
||||
|
||||
特点:
|
||||
- 实时拉取最新 K 线(不是本地文件)
|
||||
@@ -20,6 +20,7 @@ from web.data_sources.base import Bar, DataSource, DataSourceUnavailable
|
||||
|
||||
# 周期映射:CANON_TIMEFRAMES → tqsdk duration_seconds
|
||||
_TF_TO_SECONDS = {
|
||||
"5m": 300,
|
||||
"15m": 900,
|
||||
"30m": 1800,
|
||||
"1h": 3600,
|
||||
@@ -61,17 +62,25 @@ _SYMBOL_MAP = {
|
||||
|
||||
_PRESETS = list(_SYMBOL_MAP.keys())
|
||||
|
||||
# 内置默认 tqsdk 账号(web_settings.json 未配置时使用)
|
||||
_DEFAULT_TQSDK_USER = "七斗居士"
|
||||
_DEFAULT_TQSDK_PASSWORD = "ghhkphs8"
|
||||
|
||||
# web_settings.json 路径
|
||||
_SETTINGS_PATH = Path(__file__).resolve().parents[2] / "web_settings.json"
|
||||
|
||||
|
||||
def _load_credentials() -> tuple[str, str]:
|
||||
"""从 web_settings.json 读 tqsdk 账号密码。"""
|
||||
"""读取 tqsdk 账号密码。优先 web_settings.json,未配置则用内置默认账号。"""
|
||||
try:
|
||||
data = json.loads(_SETTINGS_PATH.read_text(encoding="utf-8"))
|
||||
return str(data.get("tqsdk_user", "")), str(data.get("tqsdk_password", ""))
|
||||
user = str(data.get("tqsdk_user", "")).strip()
|
||||
pwd = str(data.get("tqsdk_password", "")).strip()
|
||||
if user and pwd:
|
||||
return user, pwd
|
||||
except Exception:
|
||||
return "", ""
|
||||
pass
|
||||
return _DEFAULT_TQSDK_USER, _DEFAULT_TQSDK_PASSWORD
|
||||
|
||||
|
||||
class DomesticFuturesSource(DataSource):
|
||||
@@ -94,14 +103,10 @@ class DomesticFuturesSource(DataSource):
|
||||
return (False, "未安装 tqsdk:pip install tqsdk")
|
||||
user, pwd = _load_credentials()
|
||||
if not user or not pwd:
|
||||
return (
|
||||
False,
|
||||
"未配置 tqsdk 账号。请在 web_settings.json 设置 tqsdk_user / tqsdk_password"
|
||||
"(信易账号,https://account.shinnytech.com 注册)",
|
||||
)
|
||||
return (False, "tqsdk 账号配置异常")
|
||||
return (
|
||||
True,
|
||||
f"天勤量化实时行情 · 60 品种 · 4 周期(15m/30m/1h/1d)· 前复权",
|
||||
f"天勤量化实时行情 · 60 品种 · 5 周期(5m/15m/30m/1h/1d)· 前复权",
|
||||
)
|
||||
|
||||
def supported_timeframes(self) -> list[str]:
|
||||
@@ -132,9 +137,7 @@ class DomesticFuturesSource(DataSource):
|
||||
|
||||
user, pwd = _load_credentials()
|
||||
if not user or not pwd:
|
||||
raise DataSourceUnavailable(
|
||||
"未配置 tqsdk 账号。请在 web_settings.json 设置 tqsdk_user / tqsdk_password"
|
||||
)
|
||||
raise DataSourceUnavailable("tqsdk 账号配置异常")
|
||||
|
||||
duration = _TF_TO_SECONDS[timeframe]
|
||||
want = max(n + 5, 20) # 多拉几根防止 drop_forming 后不足
|
||||
|
||||
@@ -5,11 +5,10 @@ import threading
|
||||
|
||||
from web.data_sources.base import DataSource
|
||||
|
||||
# 前端下拉可见的数据源(okx / tongdaxin 实现保留,暂不展示)
|
||||
# 前端下拉可见的数据源(国内期货默认隐藏,如需启用加回列表即可)
|
||||
SOURCE_KINDS: tuple[tuple[str, str], ...] = (
|
||||
("mt5", "MT5"),
|
||||
("tradingview", "TradingView"),
|
||||
("domestic_futures", "国内期货"),
|
||||
)
|
||||
|
||||
_INSTANCES: dict[str, DataSource] = {}
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ _DEFAULT = {
|
||||
"feishu_webhook_url": "",
|
||||
"feishu_secret": "",
|
||||
# tqsdk 天勤量化账号(国内期货实时数据源)
|
||||
"tqsdk_user": "",
|
||||
"tqsdk_password": "",
|
||||
"tqsdk_user": "七斗居士",
|
||||
"tqsdk_password": "ghhkphs8",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1942,6 +1942,8 @@ async function initRealtimeOnce() {
|
||||
sel.innerHTML = rtSources
|
||||
.map((s) => `<option value="${s.id}">${escHtml(s.label)}${s.available ? "" : " · 未就绪"}</option>`)
|
||||
.join("");
|
||||
// 默认选第一个可用数据源
|
||||
if (rtSources.length) sel.value = rtSources[0].id;
|
||||
}
|
||||
if (data.min_exposure != null && $("rtThresholdHint")) {
|
||||
$("rtThresholdHint").textContent = `无信号阈值 |tanh(因子)| < ${data.min_exposure}`;
|
||||
|
||||
@@ -567,6 +567,6 @@
|
||||
</div>
|
||||
|
||||
<script src="/static/bg.js?v=1"></script>
|
||||
<script src="/static/app.js?v=60"></script>
|
||||
<script src="/static/app.js?v=61"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
"feishu_enabled": false,
|
||||
"feishu_webhook_url": "",
|
||||
"feishu_secret": "",
|
||||
"tqsdk_user": "",
|
||||
"tqsdk_password": ""
|
||||
"tqsdk_user": "七斗居士",
|
||||
"tqsdk_password": "ghhkphs8"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user