658 行
30 KiB
HTML
658 行
30 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>量化交易术语知识图谱 | quantKonwledge</title>
|
||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; background: #0d1117; color: #e6edf3; overflow: hidden; }
|
||
|
||
#header {
|
||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||
background: rgba(13,17,23,0.95); border-bottom: 1px solid #21262d;
|
||
padding: 12px 20px; display: flex; align-items: center; gap: 16px;
|
||
}
|
||
#header h1 { font-size: 16px; font-weight: 600; color: #58a6ff; white-space: nowrap; }
|
||
#header .subtitle { font-size: 12px; color: #8b949e; }
|
||
|
||
#controls {
|
||
display: flex; align-items: center; gap: 10px; margin-left: auto; flex-wrap: wrap;
|
||
}
|
||
.filter-btn {
|
||
padding: 4px 12px; border-radius: 20px; border: 1px solid #30363d;
|
||
background: transparent; color: #8b949e; cursor: pointer; font-size: 12px;
|
||
transition: all 0.2s;
|
||
}
|
||
.filter-btn:hover, .filter-btn.active {
|
||
border-color: currentColor; color: #e6edf3;
|
||
}
|
||
.filter-btn.cat-indicator { color: #58a6ff; }
|
||
.filter-btn.cat-trading { color: #3fb950; }
|
||
.filter-btn.cat-risk { color: #f85149; }
|
||
.filter-btn.cat-market { color: #d29922; }
|
||
.filter-btn.cat-onchain { color: #bc8cff; }
|
||
.filter-btn.cat-strategy { color: #39d353; }
|
||
.filter-btn.cat-all { color: #e6edf3; }
|
||
|
||
#search-box {
|
||
padding: 4px 12px; border-radius: 20px; border: 1px solid #30363d;
|
||
background: #161b22; color: #e6edf3; font-size: 12px; width: 160px;
|
||
outline: none;
|
||
}
|
||
#search-box:focus { border-color: #58a6ff; }
|
||
|
||
#canvas { position: fixed; top: 52px; left: 0; right: 0; bottom: 0; }
|
||
|
||
#tooltip {
|
||
position: fixed; background: rgba(22,27,34,0.97); border: 1px solid #30363d;
|
||
border-radius: 8px; padding: 12px 16px; max-width: 300px; pointer-events: none;
|
||
opacity: 0; transition: opacity 0.2s; z-index: 200; font-size: 13px;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,0.5);
|
||
}
|
||
#tooltip .tt-title { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
|
||
#tooltip .tt-cat { font-size: 11px; padding: 2px 8px; border-radius: 10px; display: inline-block; margin-bottom: 8px; }
|
||
#tooltip .tt-desc { color: #8b949e; line-height: 1.5; margin-bottom: 8px; }
|
||
#tooltip .tt-links { font-size: 12px; color: #8b949e; }
|
||
#tooltip .tt-links span { color: #58a6ff; }
|
||
|
||
#info-panel {
|
||
position: fixed; right: 0; top: 52px; bottom: 0; width: 280px;
|
||
background: rgba(13,17,23,0.97); border-left: 1px solid #21262d;
|
||
padding: 16px; overflow-y: auto; transform: translateX(100%);
|
||
transition: transform 0.3s; z-index: 150;
|
||
}
|
||
#info-panel.open { transform: translateX(0); }
|
||
#info-panel h3 { font-size: 16px; color: #58a6ff; margin-bottom: 4px; }
|
||
#info-panel .ip-cat { font-size: 11px; margin-bottom: 12px; padding: 2px 8px; border-radius: 10px; display: inline-block; }
|
||
#info-panel .ip-section { margin-bottom: 14px; }
|
||
#info-panel .ip-section h4 { font-size: 12px; color: #8b949e; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||
#info-panel .ip-section p { font-size: 13px; line-height: 1.6; color: #c9d1d9; }
|
||
#info-panel .ip-links { display: flex; flex-wrap: wrap; gap: 6px; }
|
||
#info-panel .ip-link { padding: 3px 10px; border-radius: 12px; border: 1px solid #30363d; font-size: 12px; color: #58a6ff; cursor: pointer; }
|
||
#info-panel .ip-link:hover { background: #21262d; }
|
||
#close-panel { position: absolute; top: 12px; right: 12px; background: none; border: none; color: #8b949e; cursor: pointer; font-size: 18px; }
|
||
|
||
#legend {
|
||
position: fixed; left: 16px; bottom: 16px; background: rgba(22,27,34,0.9);
|
||
border: 1px solid #21262d; border-radius: 8px; padding: 12px 16px; z-index: 100;
|
||
}
|
||
#legend h4 { font-size: 11px; color: #8b949e; margin-bottom: 8px; text-transform: uppercase; }
|
||
.legend-item { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; font-size: 12px; }
|
||
.legend-dot { width: 10px; height: 10px; border-radius: 50%; }
|
||
|
||
#stats {
|
||
position: fixed; left: 16px; top: 68px; background: rgba(22,27,34,0.9);
|
||
border: 1px solid #21262d; border-radius: 8px; padding: 10px 14px; z-index: 100;
|
||
font-size: 12px; color: #8b949e;
|
||
}
|
||
#stats span { color: #58a6ff; font-weight: 600; }
|
||
|
||
.node circle { cursor: pointer; transition: r 0.2s; }
|
||
.node circle:hover { filter: brightness(1.3); }
|
||
.node text { pointer-events: none; font-size: 11px; fill: #e6edf3; text-anchor: middle; dominant-baseline: central; }
|
||
.link { stroke: #30363d; stroke-opacity: 0.5; }
|
||
.link.highlighted { stroke-opacity: 1; stroke-width: 2; }
|
||
.node.dimmed circle { opacity: 0.15; }
|
||
.node.dimmed text { opacity: 0.15; }
|
||
.link.dimmed { stroke-opacity: 0.05; }
|
||
|
||
#hint { position: fixed; bottom: 16px; right: 16px; font-size: 11px; color: #484f58; z-index: 100; text-align: right; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div id="header">
|
||
<h1>量化交易术语知识图谱</h1>
|
||
<div class="subtitle">41 个核心术语 · 6 大类别 · 力导向关联网络</div>
|
||
<div id="controls">
|
||
<button class="filter-btn cat-all active" data-cat="all">全部</button>
|
||
<button class="filter-btn cat-indicator" data-cat="indicator">技术指标</button>
|
||
<button class="filter-btn cat-trading" data-cat="trading">交易概念</button>
|
||
<button class="filter-btn cat-risk" data-cat="risk">风险管理</button>
|
||
<button class="filter-btn cat-market" data-cat="market">市场结构</button>
|
||
<button class="filter-btn cat-onchain" data-cat="onchain">链上情绪</button>
|
||
<button class="filter-btn cat-strategy" data-cat="strategy">策略品种</button>
|
||
<input id="search-box" type="text" placeholder="搜索术语...">
|
||
</div>
|
||
</div>
|
||
|
||
<svg id="canvas"></svg>
|
||
|
||
<div id="tooltip"></div>
|
||
|
||
<div id="info-panel">
|
||
<button id="close-panel">×</button>
|
||
<h3 id="ip-title"></h3>
|
||
<span class="ip-cat" id="ip-cat"></span>
|
||
<div class="ip-section">
|
||
<h4>定义</h4>
|
||
<p id="ip-desc"></p>
|
||
</div>
|
||
<div class="ip-section">
|
||
<h4>tradehk 应用</h4>
|
||
<p id="ip-tradehk"></p>
|
||
</div>
|
||
<div class="ip-section">
|
||
<h4>关联术语</h4>
|
||
<div class="ip-links" id="ip-links"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="legend">
|
||
<h4>图例</h4>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#58a6ff"></div>技术指标</div>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#3fb950"></div>交易概念</div>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#f85149"></div>风险管理</div>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#d29922"></div>市场结构</div>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#bc8cff"></div>链上情绪</div>
|
||
<div class="legend-item"><div class="legend-dot" style="background:#39d353"></div>策略品种</div>
|
||
<div style="margin-top:8px;font-size:11px;color:#484f58">节点大小 = 被引用次数</div>
|
||
</div>
|
||
|
||
<div id="stats">
|
||
显示 <span id="stat-nodes">41</span> 个节点 · <span id="stat-links">0</span> 条关联
|
||
</div>
|
||
|
||
<div id="hint">拖拽节点 · 滚轮缩放 · 点击查看详情</div>
|
||
|
||
<script>
|
||
const CATEGORIES = {
|
||
indicator: { label: '技术指标', color: '#58a6ff' },
|
||
trading: { label: '交易概念', color: '#3fb950' },
|
||
risk: { label: '风险管理', color: '#f85149' },
|
||
market: { label: '市场结构', color: '#d29922' },
|
||
onchain: { label: '链上情绪', color: '#bc8cff' },
|
||
strategy: { label: '策略品种', color: '#39d353' }
|
||
};
|
||
|
||
const nodes = [
|
||
// 技术指标 (17)
|
||
{ id: 'EWO', label: 'EWO', cat: 'indicator', importance: 6,
|
||
desc: '艾略特波浪振荡器,计算公式为 EMA(5) - EMA(35),是 tradehk 的核心信号指标。',
|
||
tradehk: '核心指标,EWO 红→绿/绿→红转换触发飞书通知,评分权重 +2/-2。',
|
||
file: 'EWO-艾略特波浪振荡器.md' },
|
||
{ id: 'MACD', label: 'MACD', cat: 'indicator', importance: 6,
|
||
desc: '指数平滑异同移动平均线,tradehk 使用参数 (10,20,10),判断趋势方向与动量。',
|
||
tradehk: '信号评分 +1/-1,与 EWO 共振时信号更可靠。',
|
||
file: 'MACD-指数移动平均线.md' },
|
||
{ id: 'RSI', label: 'RSI', cat: 'indicator', importance: 6,
|
||
desc: '相对强弱指数,周期 14,超买区 >70,超卖区 <30。',
|
||
tradehk: '信号评分 +1/-1,多头时 RSI>50 加分,空头时 RSI<50 加分。',
|
||
file: 'RSI-相对强弱指数.md' },
|
||
{ id: 'EMA', label: 'EMA', cat: 'indicator', importance: 4,
|
||
desc: '指数移动平均线,是 EWO 和 MACD 的计算基础,赋予近期价格更高权重。',
|
||
tradehk: 'EMA(5) 和 EMA(35) 是 EWO 的直接计算来源。',
|
||
file: 'EMA-指数移动平均线.md' },
|
||
{ id: 'ATR', label: 'ATR', cat: 'indicator', importance: 5,
|
||
desc: '平均真实波动幅度,衡量市场波动性,是止损设置和仓位计算的核心参数。',
|
||
tradehk: '用于 SuperTrend 计算和动态止损设置,各品种 ATR 倍数不同。',
|
||
file: 'ATR-平均真实波动幅度.md' },
|
||
{ id: 'AO', label: 'AO', cat: 'indicator', importance: 3,
|
||
desc: '动量振荡器,计算公式为 SMA(5) - SMA(34),与 EWO 同族指标。',
|
||
tradehk: '辅助确认 EWO 信号方向,AO 与 EWO 同向时信号更强。',
|
||
file: 'AO-动量振荡器.md' },
|
||
{ id: 'KDJ', label: 'KDJ', cat: 'indicator', importance: 3,
|
||
desc: '随机指标衍生版,在 Stoch 基础上增加 J 线,对超买超卖更敏感。',
|
||
tradehk: '信号评分 +1/-1,参数 (9,3,3)。',
|
||
file: 'KDJ-随机指标衍生版.md' },
|
||
{ id: 'Stoch', label: 'Stoch', cat: 'indicator', importance: 3,
|
||
desc: '随机指标,判断当前价格在近期价格区间中的相对位置。',
|
||
tradehk: '信号评分 +1/-1,参数 (14,3,3)。',
|
||
file: 'Stoch-随机指标.md' },
|
||
{ id: 'StochRSI', label: 'StochRSI', cat: 'indicator', importance: 3,
|
||
desc: '将随机指标应用于 RSI 值,对超买超卖信号更灵敏。',
|
||
tradehk: '信号评分 +1/-1,参数 (14,14,3,3)。',
|
||
file: 'StochRSI-随机相对强弱指数.md' },
|
||
{ id: 'BollingerBands', label: '布林带', cat: 'indicator', importance: 4,
|
||
desc: '由均线和标准差构成的价格通道,反映价格波动范围和趋势。',
|
||
tradehk: '信号评分 +1/-1,价格突破上轨看多,跌破下轨看空。',
|
||
file: '布林带.md' },
|
||
{ id: 'SuperTrend', label: 'SuperTrend', cat: 'indicator', importance: 3,
|
||
desc: '基于 ATR 的趋势跟踪指标,提供清晰的多空方向和动态止损线。',
|
||
tradehk: '大周期偏向判定的核心指标之一,参数 (10, 3)。',
|
||
file: 'SuperTrend-超级趋势指标.md' },
|
||
{ id: 'TTM', label: 'TTM Squeeze', cat: 'indicator', importance: 2,
|
||
desc: '挤压动量指标,识别布林带收窄后的爆发方向。',
|
||
tradehk: '辅助判断大行情启动时机。',
|
||
file: 'TTM-Squeeze-挤压动量指标.md' },
|
||
{ id: 'OBV', label: 'OBV', cat: 'indicator', importance: 2,
|
||
desc: '能量潮指标,通过成交量累积判断资金流向。',
|
||
tradehk: '辅助确认价格趋势的成交量支撑。',
|
||
file: 'OBV-能量潮指标.md' },
|
||
{ id: 'MFI', label: 'MFI', cat: 'indicator', importance: 2,
|
||
desc: '资金流量指数,成交量加权的 RSI,判断资金进出方向。',
|
||
tradehk: '辅助判断资金面支撑。',
|
||
file: 'MFI-资金流量指数.md' },
|
||
{ id: 'DMI', label: 'DMI', cat: 'indicator', importance: 2,
|
||
desc: '趋向运动指标,通过 +DI 和 -DI 判断趋势方向。',
|
||
tradehk: '与 ADX 配合使用判断趋势强度。',
|
||
file: 'DMI-趋向运动指标.md' },
|
||
{ id: 'ADX', label: 'ADX', cat: 'indicator', importance: 2,
|
||
desc: '平均趋向指数,量化趋势强度,>25 表示趋势明显。',
|
||
tradehk: '过滤震荡市场中的假信号。',
|
||
file: 'ADX-平均趋向指数.md' },
|
||
{ id: 'MTF', label: 'MTF', cat: 'indicator', importance: 3,
|
||
desc: '多时间框架分析,通过不同周期协同确认信号方向。',
|
||
tradehk: '三层架构:4h 大周期偏向 → 1h 趋势确认 → 10m 入场信号。',
|
||
file: 'MTF-多时间框架分析.md' },
|
||
|
||
// 交易概念 (8)
|
||
{ id: 'Perpetual', label: '永续合约', cat: 'trading', importance: 5,
|
||
desc: '无到期日的期货合约,通过资金费率维持与现货价格锚定。',
|
||
tradehk: '加密货币主要交易工具,BTC/ETH/SOL 等均以永续合约为主。',
|
||
file: '永续合约.md' },
|
||
{ id: 'FundingRate', label: '资金费率', cat: 'trading', importance: 5,
|
||
desc: '永续合约多空双方定期互付的费用,正值时多头付空头,负值时反之。',
|
||
tradehk: '极端资金费率(>0.1%)是市场过热信号,可触发反向策略。',
|
||
file: '资金费率.md' },
|
||
{ id: 'Liquidation', label: '清算', cat: 'trading', importance: 5,
|
||
desc: '当仓位亏损达到保证金比例时,交易所强制平仓的机制。',
|
||
tradehk: '清算价格计算:入场价 × (1 - 1/杠杆 + 维持保证金率)。',
|
||
file: '清算.md' },
|
||
{ id: 'Short', label: '做空', cat: 'trading', importance: 3,
|
||
desc: '通过借入资产卖出,预期价格下跌后低价买回获利的交易方式。',
|
||
tradehk: 'EWO 绿→红转换时触发做空信号,需结合大周期偏向确认。',
|
||
file: '做空.md' },
|
||
{ id: 'LongShortRatio', label: '多空比', cat: 'trading', importance: 3,
|
||
desc: '市场中多头持仓与空头持仓的比例,反映市场情绪偏向。',
|
||
tradehk: '多空比极端值(>3 或 <0.5)可作为反转信号参考。',
|
||
file: '多空比.md' },
|
||
{ id: 'Slippage', label: '滑点', cat: 'trading', importance: 3,
|
||
desc: '实际成交价格与预期价格之间的差异,是交易执行成本的重要组成。',
|
||
tradehk: '回测时必须计入滑点,BTC 约 0.02%,DOGE 约 0.1%。',
|
||
file: '滑点.md' },
|
||
{ id: 'MarketMaker', label: '做市商', cat: 'trading', importance: 2,
|
||
desc: '通过持续提供买卖报价为市场提供流动性的机构或个人。',
|
||
tradehk: 'Hyperliquid HLP Vault 本质上是去中心化做市商。',
|
||
file: '做市商.md' },
|
||
{ id: 'Backtest', label: '回测', cat: 'trading', importance: 4,
|
||
desc: '使用历史数据验证交易策略表现的方法,是量化交易的必要环节。',
|
||
tradehk: '需避免前视偏差,IS/OOS 比率应 >0.7,参数稳健性测试必须通过。',
|
||
file: '回测.md' },
|
||
|
||
// 风险管理 (6)
|
||
{ id: 'Kelly', label: 'Kelly 公式', cat: 'risk', importance: 4,
|
||
desc: '最优仓位计算公式:f = (bp - q) / b,根据胜率和赔率确定最优仓位比例。',
|
||
tradehk: '建议使用 1/4 Kelly(保守版),BTC 建议最大仓位 25%。',
|
||
file: 'Kelly公式.md' },
|
||
{ id: 'Sharpe', label: '夏普比率', cat: 'risk', importance: 4,
|
||
desc: '风险调整后收益指标,计算公式为 (Rp - Rf) / σp,>1 为合格,>2 为优秀。',
|
||
tradehk: '策略评估核心指标,目标夏普比率 >1.5。',
|
||
file: '夏普比率.md' },
|
||
{ id: 'MaxDrawdown', label: '最大回撤', cat: 'risk', importance: 4,
|
||
desc: '从历史最高点到最低点的最大亏损幅度,衡量策略最坏情况。',
|
||
tradehk: '最大回撤 >20% 触发策略暂停,>30% 触发全面审查。',
|
||
file: '最大回撤.md' },
|
||
{ id: 'PositionSizing', label: '仓位管理', cat: 'risk', importance: 5,
|
||
desc: '决定每笔交易投入资金比例的方法,是风险控制的核心。',
|
||
tradehk: '单笔风险不超过总资金 2%,ATR 止损法:仓位 = 风险金额 / (ATR × 倍数)。',
|
||
file: '仓位管理.md' },
|
||
{ id: 'FearGreed', label: '恐惧贪婪指数', cat: 'risk', importance: 3,
|
||
desc: '综合多个市场情绪指标的 0-100 指数,<25 极度恐惧,>75 极度贪婪。',
|
||
tradehk: '极度恐惧时 EWO 绿信号可靠性更高,极度贪婪时需谨慎做多。',
|
||
file: '恐惧贪婪指数.md' },
|
||
{ id: 'QuantTrading', label: '量化交易', cat: 'risk', importance: 3,
|
||
desc: '使用数学模型和计算机程序进行交易决策的方法论。',
|
||
tradehk: 'tradehk 是量化交易系统的实践案例。',
|
||
file: '量化交易.md' },
|
||
|
||
// 市场结构 (5)
|
||
{ id: 'CEX', label: 'CEX', cat: 'market', importance: 3,
|
||
desc: '中心化交易所,由中心化机构运营,提供订单簿撮合服务。',
|
||
tradehk: 'Binance、OKX 是主要数据来源,API 获取 K 线数据。',
|
||
file: 'CEX-中心化交易所.md' },
|
||
{ id: 'DEX', label: 'DEX', cat: 'market', importance: 3,
|
||
desc: '去中心化交易所,通过智能合约实现无需信任的资产交换。',
|
||
tradehk: 'Hyperliquid 是链上永续合约 DEX 的代表。',
|
||
file: 'DEX-去中心化交易所.md' },
|
||
{ id: 'Hyperliquid', label: 'Hyperliquid', cat: 'market', importance: 4,
|
||
desc: '链上永续合约交易所,HLP Vault 提供流动性,日均交易量超 10 亿美元。',
|
||
tradehk: '可作为 tradehk 信号的执行平台之一,需注意链上延迟。',
|
||
file: 'Hyperliquid.md' },
|
||
{ id: 'XAUT', label: 'XAUT', cat: 'market', importance: 3,
|
||
desc: '代币化黄金,1 XAUT = 1 金衡盎司黄金,与加密市场负相关。',
|
||
tradehk: 'FOMC 前后 48h 暂停信号,宏观事件过滤是关键。',
|
||
file: 'XAUT-黄金代币.md' },
|
||
{ id: 'TokenizedStocks', label: '代币化美股', cat: 'market', importance: 3,
|
||
desc: 'xAAPL/xTSLA/xNVDA 等代币化美股,仅在美股交易时间内有效信号。',
|
||
tradehk: '需过滤非交易时段(美东 9:30-16:00),财报季暂停交易。',
|
||
file: '代币化美股.md' },
|
||
|
||
// 链上情绪 (3)
|
||
{ id: 'MVRV', label: 'MVRV', cat: 'onchain', importance: 3,
|
||
desc: '市值与已实现价值之比,>3.5 历史顶部区域,<1 历史底部区域。',
|
||
tradehk: '宏观择时指标,MVRV>3 时降低杠杆,<1 时可加大仓位。',
|
||
file: 'MVRV-市值已实现价值比.md' },
|
||
{ id: 'OnchainData', label: '链上数据', cat: 'onchain', importance: 3,
|
||
desc: '区块链上可公开查询的交易数据,包括 SOPR、MVRV、鲸鱼动向等。',
|
||
tradehk: '辅助判断市场周期位置,与技术信号结合使用。',
|
||
file: '链上数据.md' },
|
||
|
||
// 策略品种 (5)
|
||
{ id: 'TrendTrading', label: '趋势交易', cat: 'strategy', importance: 3,
|
||
desc: '顺势而为的交易策略,通过识别趋势方向并持仓获利。',
|
||
tradehk: 'EWO 绿色阶段做多、红色阶段做空是趋势交易的核心逻辑。',
|
||
file: '趋势交易.md' },
|
||
{ id: 'Arbitrage', label: '套利策略', cat: 'strategy', importance: 3,
|
||
desc: '利用市场价格差异获利的策略,包括期现套利、跨所套利等。',
|
||
tradehk: '资金费率套利:当费率 >0.1% 时,做空永续合约同时做多现货。',
|
||
file: '套利策略.md' },
|
||
{ id: 'Perpetual2', label: '永续合约2', cat: 'strategy', importance: 1,
|
||
desc: '(见交易概念类)', tradehk: '', file: '永续合约.md' }
|
||
];
|
||
|
||
// 过滤掉重复节点
|
||
const filteredNodes = nodes.filter(n => n.id !== 'Perpetual2');
|
||
|
||
const links = [
|
||
// EWO 关联
|
||
{ source: 'EWO', target: 'EMA', strength: 3 },
|
||
{ source: 'EWO', target: 'AO', strength: 2 },
|
||
{ source: 'EWO', target: 'Short', strength: 2 },
|
||
{ source: 'EWO', target: 'Backtest', strength: 2 },
|
||
{ source: 'EWO', target: 'MTF', strength: 2 },
|
||
{ source: 'EWO', target: 'TrendTrading', strength: 2 },
|
||
|
||
// MACD 关联
|
||
{ source: 'MACD', target: 'EMA', strength: 3 },
|
||
{ source: 'MACD', target: 'RSI', strength: 3 },
|
||
{ source: 'MACD', target: 'KDJ', strength: 2 },
|
||
{ source: 'MACD', target: 'Stoch', strength: 2 },
|
||
{ source: 'MACD', target: 'StochRSI', strength: 2 },
|
||
{ source: 'MACD', target: 'OBV', strength: 2 },
|
||
{ source: 'MACD', target: 'BollingerBands', strength: 2 },
|
||
|
||
// RSI 关联
|
||
{ source: 'RSI', target: 'BollingerBands', strength: 2 },
|
||
{ source: 'RSI', target: 'KDJ', strength: 2 },
|
||
{ source: 'RSI', target: 'Stoch', strength: 2 },
|
||
{ source: 'RSI', target: 'StochRSI', strength: 3 },
|
||
{ source: 'RSI', target: 'MFI', strength: 2 },
|
||
{ source: 'RSI', target: 'MTF', strength: 2 },
|
||
{ source: 'RSI', target: 'DMI', strength: 2 },
|
||
|
||
// ATR 关联
|
||
{ source: 'ATR', target: 'BollingerBands', strength: 2 },
|
||
{ source: 'ATR', target: 'SuperTrend', strength: 3 },
|
||
{ source: 'ATR', target: 'TTM', strength: 2 },
|
||
{ source: 'ATR', target: 'PositionSizing', strength: 3 },
|
||
{ source: 'ATR', target: 'Liquidation', strength: 2 },
|
||
{ source: 'ATR', target: 'XAUT', strength: 2 },
|
||
|
||
// EMA 关联
|
||
{ source: 'EMA', target: 'TrendTrading', strength: 2 },
|
||
|
||
// DMI/ADX
|
||
{ source: 'DMI', target: 'ADX', strength: 3 },
|
||
|
||
// 永续合约关联
|
||
{ source: 'Perpetual', target: 'FundingRate', strength: 3 },
|
||
{ source: 'Perpetual', target: 'Liquidation', strength: 3 },
|
||
{ source: 'Perpetual', target: 'Short', strength: 2 },
|
||
{ source: 'Perpetual', target: 'Hyperliquid', strength: 2 },
|
||
{ source: 'Perpetual', target: 'TokenizedStocks', strength: 2 },
|
||
{ source: 'Perpetual', target: 'XAUT', strength: 2 },
|
||
{ source: 'Perpetual', target: 'Arbitrage', strength: 2 },
|
||
|
||
// 资金费率关联
|
||
{ source: 'FundingRate', target: 'Arbitrage', strength: 3 },
|
||
{ source: 'FundingRate', target: 'Hyperliquid', strength: 2 },
|
||
{ source: 'FundingRate', target: 'LongShortRatio', strength: 2 },
|
||
{ source: 'FundingRate', target: 'OnchainData', strength: 2 },
|
||
|
||
// 清算关联
|
||
{ source: 'Liquidation', target: 'PositionSizing', strength: 3 },
|
||
{ source: 'Liquidation', target: 'Kelly', strength: 2 },
|
||
{ source: 'Liquidation', target: 'MaxDrawdown', strength: 2 },
|
||
{ source: 'Liquidation', target: 'Hyperliquid', strength: 2 },
|
||
|
||
// 风险管理关联
|
||
{ source: 'Kelly', target: 'PositionSizing', strength: 3 },
|
||
{ source: 'Kelly', target: 'Backtest', strength: 2 },
|
||
{ source: 'Sharpe', target: 'MaxDrawdown', strength: 3 },
|
||
{ source: 'Sharpe', target: 'Backtest', strength: 2 },
|
||
{ source: 'Sharpe', target: 'PositionSizing', strength: 2 },
|
||
{ source: 'MaxDrawdown', target: 'Backtest', strength: 2 },
|
||
{ source: 'PositionSizing', target: 'Slippage', strength: 2 },
|
||
{ source: 'Backtest', target: 'Slippage', strength: 2 },
|
||
{ source: 'Backtest', target: 'QuantTrading', strength: 2 },
|
||
|
||
// 市场结构关联
|
||
{ source: 'CEX', target: 'DEX', strength: 3 },
|
||
{ source: 'CEX', target: 'Slippage', strength: 2 },
|
||
{ source: 'DEX', target: 'Hyperliquid', strength: 3 },
|
||
{ source: 'DEX', target: 'Slippage', strength: 2 },
|
||
{ source: 'Hyperliquid', target: 'MarketMaker', strength: 2 },
|
||
{ source: 'Hyperliquid', target: 'LongShortRatio', strength: 2 },
|
||
{ source: 'MarketMaker', target: 'Slippage', strength: 2 },
|
||
|
||
// 链上数据关联
|
||
{ source: 'MVRV', target: 'OnchainData', strength: 3 },
|
||
{ source: 'OnchainData', target: 'FearGreed', strength: 2 },
|
||
{ source: 'FearGreed', target: 'LongShortRatio', strength: 2 },
|
||
|
||
// 策略关联
|
||
{ source: 'TrendTrading', target: 'MTF', strength: 2 },
|
||
{ source: 'Arbitrage', target: 'Slippage', strength: 2 },
|
||
{ source: 'Short', target: 'LongShortRatio', strength: 2 },
|
||
{ source: 'Short', target: 'PositionSizing', strength: 2 },
|
||
{ source: 'TokenizedStocks', target: 'CEX', strength: 2 },
|
||
{ source: 'XAUT', target: 'MTF', strength: 2 },
|
||
{ source: 'XAUT', target: 'CEX', strength: 2 },
|
||
];
|
||
|
||
// 计算节点被引用次数(入度)
|
||
const inDegree = {};
|
||
filteredNodes.forEach(n => inDegree[n.id] = 0);
|
||
links.forEach(l => {
|
||
if (inDegree[l.target] !== undefined) inDegree[l.target]++;
|
||
if (inDegree[l.source] !== undefined) inDegree[l.source]++;
|
||
});
|
||
|
||
// 设置 SVG
|
||
const svg = d3.select('#canvas');
|
||
const width = window.innerWidth;
|
||
const height = window.innerHeight - 52;
|
||
svg.attr('width', width).attr('height', height);
|
||
|
||
const g = svg.append('g');
|
||
|
||
// 缩放
|
||
const zoom = d3.zoom()
|
||
.scaleExtent([0.3, 3])
|
||
.on('zoom', (event) => g.attr('transform', event.transform));
|
||
svg.call(zoom);
|
||
|
||
// 力导向模拟
|
||
const simulation = d3.forceSimulation(filteredNodes)
|
||
.force('link', d3.forceLink(links).id(d => d.id).distance(d => 120 - d.strength * 15).strength(d => d.strength * 0.15))
|
||
.force('charge', d3.forceManyBody().strength(-300))
|
||
.force('center', d3.forceCenter(width / 2, height / 2))
|
||
.force('collision', d3.forceCollide().radius(d => getRadius(d) + 12));
|
||
|
||
function getRadius(d) {
|
||
const base = 14;
|
||
const extra = Math.min((inDegree[d.id] || 0) * 2.5, 20);
|
||
return base + extra;
|
||
}
|
||
|
||
function getColor(cat) {
|
||
return CATEGORIES[cat]?.color || '#8b949e';
|
||
}
|
||
|
||
// 绘制连线
|
||
const link = g.append('g').selectAll('.link')
|
||
.data(links).enter().append('line')
|
||
.attr('class', 'link')
|
||
.attr('stroke', d => {
|
||
const src = filteredNodes.find(n => n.id === d.source.id || n.id === d.source);
|
||
return src ? getColor(src.cat) : '#30363d';
|
||
})
|
||
.attr('stroke-width', d => d.strength * 0.6);
|
||
|
||
// 绘制节点
|
||
const node = g.append('g').selectAll('.node')
|
||
.data(filteredNodes).enter().append('g')
|
||
.attr('class', 'node')
|
||
.call(d3.drag()
|
||
.on('start', (event, d) => { if (!event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
|
||
.on('drag', (event, d) => { d.fx = event.x; d.fy = event.y; })
|
||
.on('end', (event, d) => { if (!event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; })
|
||
);
|
||
|
||
node.append('circle')
|
||
.attr('r', d => getRadius(d))
|
||
.attr('fill', d => getColor(d.cat))
|
||
.attr('fill-opacity', 0.85)
|
||
.attr('stroke', d => getColor(d.cat))
|
||
.attr('stroke-width', 1.5)
|
||
.attr('stroke-opacity', 0.5);
|
||
|
||
node.append('text')
|
||
.text(d => d.label)
|
||
.attr('font-size', d => getRadius(d) > 25 ? '12px' : '10px')
|
||
.attr('fill', '#fff');
|
||
|
||
// 更新统计
|
||
document.getElementById('stat-links').textContent = links.length;
|
||
|
||
// Tooltip
|
||
const tooltip = document.getElementById('tooltip');
|
||
node.on('mouseover', (event, d) => {
|
||
const connectedIds = new Set();
|
||
links.forEach(l => {
|
||
const srcId = l.source.id || l.source;
|
||
const tgtId = l.target.id || l.target;
|
||
if (srcId === d.id) connectedIds.add(tgtId);
|
||
if (tgtId === d.id) connectedIds.add(srcId);
|
||
});
|
||
tooltip.innerHTML = `
|
||
<div class="tt-title">${d.label}</div>
|
||
<span class="tt-cat" style="background:${getColor(d.cat)}22;color:${getColor(d.cat)}">${CATEGORIES[d.cat]?.label}</span>
|
||
<div class="tt-desc">${d.desc}</div>
|
||
<div class="tt-links">关联术语:<span>${connectedIds.size} 个</span> · 引用次数:<span>${inDegree[d.id]}</span></div>
|
||
`;
|
||
tooltip.style.opacity = 1;
|
||
tooltip.style.left = (event.clientX + 16) + 'px';
|
||
tooltip.style.top = (event.clientY - 10) + 'px';
|
||
|
||
// 高亮关联节点
|
||
node.classed('dimmed', n => n.id !== d.id && !connectedIds.has(n.id));
|
||
link.classed('dimmed', l => {
|
||
const srcId = l.source.id || l.source;
|
||
const tgtId = l.target.id || l.target;
|
||
return srcId !== d.id && tgtId !== d.id;
|
||
});
|
||
link.classed('highlighted', l => {
|
||
const srcId = l.source.id || l.source;
|
||
const tgtId = l.target.id || l.target;
|
||
return srcId === d.id || tgtId === d.id;
|
||
});
|
||
})
|
||
.on('mousemove', (event) => {
|
||
tooltip.style.left = (event.clientX + 16) + 'px';
|
||
tooltip.style.top = (event.clientY - 10) + 'px';
|
||
})
|
||
.on('mouseout', () => {
|
||
tooltip.style.opacity = 0;
|
||
node.classed('dimmed', false);
|
||
link.classed('dimmed', false);
|
||
link.classed('highlighted', false);
|
||
})
|
||
.on('click', (event, d) => {
|
||
const panel = document.getElementById('info-panel');
|
||
const connectedIds = [];
|
||
links.forEach(l => {
|
||
const srcId = l.source.id || l.source;
|
||
const tgtId = l.target.id || l.target;
|
||
if (srcId === d.id) connectedIds.push(tgtId);
|
||
if (tgtId === d.id) connectedIds.push(srcId);
|
||
});
|
||
const uniqueIds = [...new Set(connectedIds)];
|
||
|
||
document.getElementById('ip-title').textContent = d.label;
|
||
const catEl = document.getElementById('ip-cat');
|
||
catEl.textContent = CATEGORIES[d.cat]?.label;
|
||
catEl.style.background = getColor(d.cat) + '22';
|
||
catEl.style.color = getColor(d.cat);
|
||
document.getElementById('ip-desc').textContent = d.desc;
|
||
document.getElementById('ip-tradehk').textContent = d.tradehk || '暂无 tradehk 专项说明';
|
||
|
||
const linksEl = document.getElementById('ip-links');
|
||
linksEl.innerHTML = uniqueIds.map(id => {
|
||
const n = filteredNodes.find(n => n.id === id);
|
||
if (!n) return '';
|
||
return `<span class="ip-link" style="border-color:${getColor(n.cat)};color:${getColor(n.cat)}" onclick="highlightNode('${id}')">${n.label}</span>`;
|
||
}).join('');
|
||
|
||
panel.classList.add('open');
|
||
});
|
||
|
||
document.getElementById('close-panel').addEventListener('click', () => {
|
||
document.getElementById('info-panel').classList.remove('open');
|
||
});
|
||
|
||
// 高亮指定节点
|
||
window.highlightNode = function(id) {
|
||
const d = filteredNodes.find(n => n.id === id);
|
||
if (!d) return;
|
||
simulation.alpha(0.3).restart();
|
||
svg.transition().duration(500).call(
|
||
zoom.transform,
|
||
d3.zoomIdentity.translate(width/2 - d.x, height/2 - d.y)
|
||
);
|
||
};
|
||
|
||
// 分类过滤
|
||
let activeFilter = 'all';
|
||
document.querySelectorAll('.filter-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
activeFilter = btn.dataset.cat;
|
||
applyFilter();
|
||
});
|
||
});
|
||
|
||
function applyFilter() {
|
||
const search = document.getElementById('search-box').value.toLowerCase();
|
||
node.style('display', d => {
|
||
const catMatch = activeFilter === 'all' || d.cat === activeFilter;
|
||
const searchMatch = !search || d.label.toLowerCase().includes(search) || d.desc.toLowerCase().includes(search);
|
||
return catMatch && searchMatch ? null : 'none';
|
||
});
|
||
const visibleIds = new Set(filteredNodes.filter(d => {
|
||
const catMatch = activeFilter === 'all' || d.cat === activeFilter;
|
||
const searchMatch = !search || d.label.toLowerCase().includes(search) || d.desc.toLowerCase().includes(search);
|
||
return catMatch && searchMatch;
|
||
}).map(d => d.id));
|
||
link.style('display', l => {
|
||
const srcId = l.source.id || l.source;
|
||
const tgtId = l.target.id || l.target;
|
||
return visibleIds.has(srcId) && visibleIds.has(tgtId) ? null : 'none';
|
||
});
|
||
document.getElementById('stat-nodes').textContent = visibleIds.size;
|
||
}
|
||
|
||
document.getElementById('search-box').addEventListener('input', applyFilter);
|
||
|
||
// 物理模拟更新
|
||
simulation.on('tick', () => {
|
||
link
|
||
.attr('x1', d => d.source.x).attr('y1', d => d.source.y)
|
||
.attr('x2', d => d.target.x).attr('y2', d => d.target.y);
|
||
node.attr('transform', d => `translate(${d.x},${d.y})`);
|
||
});
|
||
|
||
// 响应窗口大小
|
||
window.addEventListener('resize', () => {
|
||
const w = window.innerWidth, h = window.innerHeight - 52;
|
||
svg.attr('width', w).attr('height', h);
|
||
simulation.force('center', d3.forceCenter(w/2, h/2)).alpha(0.3).restart();
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|