做量化或者盯盘的朋友,应该都听过TradingView的大名,也大概率在近半年被MCP这个词刷屏了。tradingview-mcp就是把这两件事接起来:让AI助手能直接去读TradingView的行情数据、技术指标,甚至操作图表界面。我在本地把这套链路完整跑通之后,最大的感受是——之前让AI帮我写策略,它只能对着"你手动复制的K线数据"干活;现在AI自己就能拉数据、算指标、找品种,整个工作流顺畅了不止一个档次。这篇文章就把我搭建tradingview-mcp的完整过程、踩过的坑、以及能直接抄作业的配置全部分享出来。
1. 先弄清楚:TradingView和MCP到底能拼出什么
1.1 两个热词的本质
先说TradingView。它本质是一个基于Web的金融图表平台,支持股票、加密货币、外汇、期货等几乎所有主流交易品种。大家平时用的最多的是它的图表界面:K线、画线工具、几十种内置技术指标、策略回测,这些功能非常成熟。但TradingView并不是一个完全开源的软件,它开放给开发者的主要是两类东西:一类是图表库(Lightweight Charts、Advanced Charts),可以集成到自己的网页项目里;另一类是各种API接口,包括webhook、Scanner行情接口、以及面向第三方平台的集成能力。热词里反复出现的"tradingview源码本地部署",说的其实不是把整个TradingView网站源码搬回家,而是把它的图表库和行情数据链路集成到自己的本地项目里,形成一个可以自托管的图表环境。
再说MCP,全称Model Context Protocol,模型上下文协议。你可以把它理解成AI应用和外部工具之间的"标准USB接口"。以前想让AI读取某个数据源或者操作某个软件,每个AI产品都得单独做集成,适配成本很高;MCP出现之后,数据源和工具只要实现一次MCP Server,任何支持MCP的AI助手(Claude Desktop、Cursor、Codex、Trae、各类Agent框架)都能直接调用。这个思路在热词里很明显——figma mcp、蓝湖mcp、ida mcp、playwright mcp都是同一类东西:把某个垂直工具的能力通过MCP暴露给AI。
tradingview-mcp就是这两者结合的产物。它作为一个MCP Server,把TradingView生态里的行情数据和图表能力封装成AI可以调用的工具函数。AI收到"最近BTC的RSI是多少""帮我找今天放量的美股标的""把ETHUSDT切到15分钟图"这类指令时,不再需要你去手动截图或复制数据,而是直接通过MCP Server拿到结构化结果。
1.2 接入MCP后,AI能替代我做什么
把这个项目搭好之后,能做的事情比我最初预期的要多。最基础的是数据查询:让AI拉取指定品种的K线数据、最新价格、涨跌幅;稍微进阶一点的是技术指标分析:AI可以自己算RSI、MACD、布林带,或者直接读取TradingView扫描接口返回的"综合建议";再进一步就是图表操作能力:配合Playwright这类浏览器自动化MCP,AI可以在网页版TradingView里切换交易对、切换周期、截图当前图表,然后基于图像信息继续分析。
这个能力对两类人价值最大。第一类是量化策略开发者,写策略之前需要快速看数据、验证想法,过去要写一堆脚本拉数据,现在直接对话就能完成探索性分析;第二类是普通交易者,不想折腾代码,但是想让AI帮忙盯盘、生成技术面解读、甚至根据指标条件做筛选提醒。当然,MCP不是万能的,它本质是"工具调用",AI的分析结论还是需要人工把关,但至少把"人找数据"变成了"AI找数据",这一步的效率提升是实打实的。
1.3 方案选型:数据API直连,还是浏览器自动化
做tradingview-mcp,第一道分岔路就是用哪种方式去对接TradingView。我在调研和实测之后,把它分成两个主流路线。
第一个路线是"API数据直连"。TradingView有对外开放的Scanner接口和图表数据接口,同时还有大量公共行情API可以作为补充数据源。这种方案不依赖浏览器,MCP Server直接发HTTP请求拉JSON数据,速度快、稳定性高、资源占用低。适合做数据查询、指标计算、选币筛选这类偏"结构化数据"的任务。
第二个路线是"浏览器自动化控制"。通过Playwright MCP或者自写的浏览器控制逻辑,打开真实的TradingView网页版,模拟人来操作:切换交易对、切换周期、读取图表上渲染出的图形和数值。这种方案能拿到真实渲染后的图表截图、图形状态,适合做"看图说话"类任务,但缺点是重、慢、且对网页DOM结构变化敏感。
我的建议是两条腿走路:核心数据查询走API直连,需要视觉理解的时候再用Playwright补充。这正好也呼应了热词里"playwright mcp"和"browserskill和agent browser以及playwrite mcp"的讨论——浏览器自动化MCP适合的是"操作界面"场景,而数据型MCP适合"拿数据"场景。下面我重点讲API直连路线的完整搭建过程,然后在进阶部分给Playwright方案的关键思路。
2. 动手前准备:架构、环境与数据源取舍
2.1 MCP体系架构速览(Host/Client/Server的三角关系)
热词里有人问"mcp host和mcp server"的区别,这里必须先把这个关系捋清楚,否则后面配置会一头雾水。MCP体系里有三个角色:
- MCP Host:运行AI模型和对话逻辑的主程序,比如Claude Desktop、Cursor、Codex、Trae等。你在这个界面里提问。
- MCP Client:内嵌在Host里的连接组件,负责在Host和Server之间建立通信、转发工具调用请求。
- MCP Server:独立的进程或服务,实现具体的工具逻辑,暴露给Client调用。咱们要写的tradingview-mcp就属于这个角色。
它们的关系很直观:你在Host里说"查一下AAPL的RSI",Host把这句话交给LLM,LLM决定调用一个名为get_technical_analysis的工具,MCP Client把这个请求通过本地IPC(进程间通信)发送给MCP Server,Server执行真实的数据拉取,把结果原路返回,最后由LLM组织成自然语言回答你。
MCP Server的开发可以基于官方Python SDK或TypeScript SDK,也可以用FastMCP这类封装库。我个人用Python生态更多,下面所有代码都基于Python + FastMCP实现,这也是目前社区里最主流的写法。
2.2 本地环境准备与依赖安装
搭建这套环境,我建议用一个独立的Python虚拟环境,避免和系统Python打架。Python版本需要3.10以上,实测3.11最稳。创建并激活环境:
python3.11 -m venv .venv source .venv/bin/activate # Windows下为 .venv\Scripts\activate然后安装核心依赖:
pip install fastmcp requestsFastMCP目前是MCP官方推荐的快速开发库之一,它把Server的生命周期管理、工具注册、传输协议全部封装好了,我们只需要定义函数、加一个装饰器,就能得到一个可用的MCP Server。requests用于发HTTP请求拉行情数据。
另外,如果你后面要用Playwright方案,还需要额外安装:
pip install playwright playwright install chromium这里提醒一句,Playwright首次下载浏览器内核会比较慢,建议提前找网络环境好的时候装好。
2.3 数据源选型:TradingView接口、公共交易所API与本地图表库
tradingview-mcp的"数据"到底从哪里来,这个问题直接决定了项目能不能稳定跑起来。我梳理了三个数据来源,各有优劣。
第一,TradingView官方Scanner接口。这个接口是TradingView网页端用来做市场扫描的,虽然是非公开文档,但多年以来一直稳定可用。它的特点是可以一次返回大量交易品种的行情快照和技术指标数据,非常适合做"全市场扫描、条件筛选、指标汇总"类任务。我后面代码里会用https://scanner.tradingview.com/{market}/scan,其中market可以换成crypto、america、forex等。
第二,公共交易所API,比如Binance的api.binance.com/api/v3/klines。这类接口的优势是稳定、文档完善、无鉴权(大部分公共接口),适合拿详细的K线数据。在TradingView接口拿不到某些K线细节时,用交易所API做兜底非常合适。
第三,本地集成的TradingView图表库。如果你需要"本地部署"的图表环境,可以npm安装lightweight-charts或申请Advanced Charts的授权key,把它集成到自己的前端项目里。但要注意,这解决的是"图表怎么画"的问题,数据源还是需要自己接。所以在架构上,我更推荐"TradingView图表库负责展示 + MCP Server负责数据管道"的组合。
我最终采用的方案是混合型:Scanner接口负责技术指标和市场扫描,交易所API负责K线和撮合类数据,MCP Server做统一封装。这样一个Server就能覆盖大部分需求,而且不依赖任何单一数据源。
3. 核心实操:搭建一个最小可用的tradingview-mcp Server
3.1 项目骨架与配置文件
整个项目不需要复杂的脚手架,一个Python文件就能启动。我习惯的目录结构是这样:
tradingview-mcp/ ├── tv_mcp.py # MCP Server主文件 ├── requirements.txt # 依赖清单 └── config.json # 数据源相关配置(可选)requirements.txt内容如下:
fastmcp>=2.0.0 requests>=2.31.0config.json用来配置Scanner接口的默认市场、默认K线长度等,我习惯把这类可调项外置,方便切换:
{ "default_market": "crypto", "default_symbol": "BTCUSDT", "default_interval": "1h", "default_bar_limit": 200 }如果你不想用配置文件,直接在代码里写默认值也行,但外置的好处是换个市场、换个标的时不用动代码。
3.2 核心代码拆解:K线读取、品种搜索与技术分析
先看完整代码,然后我逐段拆解。这个文件我实测过,FastMCP会直接把它变成一个标准的MCP Server进程。
import json import os import time import requests from fastmcp import FastMCP # 读取配置文件(可选) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) CONFIG_PATH = os.path.join(BASE_DIR, "config.json") DEFAULT_CONFIG = { "default_market": "crypto", "default_symbol": "BTCUSDT", "default_interval": "1h", "default_bar_limit": 200, } def load_config(): if os.path.exists(CONFIG_PATH): with open(CONFIG_PATH, "r", encoding="utf-8") as f: return {**DEFAULT_CONFIG, **json.load(f)} return DEFAULT_CONFIG CONFIG = load_config() # 创建MCP Server实例 mcp = FastMCP("tradingview-mcp") # ---------- Helper函数 ---------- def get_scan_endpoint(market: str) -> str: """根据市场名返回TradingView Scanner接口地址""" market_map = { "crypto": "crypto", "america": "america", "forex": "forex", "cfd": "cfd", "crypto_v2": "crypto_v2", "crypto_hot": "crypto_hot", } mkt = market_map.get(market, "crypto") return f"https://scanner.tradingview.com/{mkt}/scan" def tv_scan(market: str, tickers: list[str], columns: list[str]) -> dict: """调用TradingView Scanner接口""" endpoint = get_scan_endpoint(market) payload = { "symbols": {"tickers": tickers}, "columns": columns, } resp = requests.post(endpoint, json=payload, timeout=10) resp.raise_for_status() return resp.json() def binance_klines(symbol: str, interval: str, limit: int = 200) -> list: """从Binance公共接口获取K线,作为兜底数据源""" base = "https://api.binance.com/api/v3/klines" params = {"symbol": symbol.upper(), "interval": interval, "limit": limit} resp = requests.get(base, params=params, timeout=10) resp.raise_for_status() data = resp.json() result = [] for item in data: # Binance kline格式: [openTime, open, high, low, close, volume, ...] result.append({ "open_time": item[0], "open": float(item[1]), "high": float(item[2]), "low": float(item[3]), "close": float(item[4]), "volume": float(item[5]), }) return result # ---------- MCP工具函数 ---------- @mcp.tool() def search_symbols(query: str, market: str = "crypto") -> dict: """在TradingView扫描器中搜索交易品种。 Args: query: 搜索关键词,如 "BTC"。 market: 市场类型,可选 crypto/america/forex 等。 """ columns = ["name", "description", "close", "change", "volume"] # 这里使用Scanner的ts搜索前缀,也可以直接用名称拉取 tickers = [f"{market}:{query}" if not query.startswith("exchange") else query] data = tv_scan(market, tickers, columns) return data @mcp.tool() def get_klines(symbol: str = "BTCUSDT", interval: str = "1h", limit: int = 200, source: str = "auto") -> dict: """获取K线数据。 Args: symbol: 交易对或股票代码。 interval: K线周期,支持 1m/5m/15m/1h/4h/1d 等。 limit: 返回K线条数,最多1000。 source: 数据源,auto表示自动选择,也可以指定 binance。 """ limit = min(max(limit, 1), 1000) data = binance_klines(symbol, interval, limit) return { "symbol": symbol, "interval": interval, "source": "binance", "bars": data, } @mcp.tool() def get_technical_analysis(symbol: str = "BTCUSDT", market: str = "crypto", indicators: list[str] | None = None) -> dict: """获取TradingView技术指标汇总。 Args: symbol: 交易品种代码。 market: 市场类型,默认crypto。 indicators: 需要的指标列,默认使用RSI/MACD/MA等常用项。 """ default_columns = [ "name", "close", "change", "volume", "RSI", "RSI[1]", "MACD.macd", "MACD.signal", "EMA10", "EMA20", "EMA50", "SMA20", "SMA50", "SMA200", "Recommend.All", "Recommend.MA", "Recommend.MACD" ] cols = indicators if indicators else default_columns raw = tv_scan(market, [symbol], cols) return raw @mcp.tool() def scan_market(market: str = "crypto", columns: list[str] | None = None, filter_json: str = "{}", limit: int = 20) -> dict: """扫描整个市场,根据条件筛选品种。 Args: market: 市场类型。 columns: 返回的指标列。 filter_json: 过滤条件,JSON字符串,如 '{"change":{"gte":5}}'。 limit: 返回数量上限。 """ default_columns = ["name", "close", "change", "volume", "RSI", "Recommend.All"] cols = columns if columns else default_columns payload_filter = json.loads(filter_json) if filter_json else {} endpoint = get_scan_endpoint(market) payload = { "symbols": {"tickers": [], "query": {"types": []}}, "columns": cols, "filter": payload_filter, "options": {}, "range": [0, limit], } resp = requests.post(endpoint, json=payload, timeout=10) resp.raise_for_status() return resp.json() @mcp.tool() def get_quote(symbol: str = "BTCUSDT", market: str = "crypto") -> dict: """获取单个品种的最新报价和涨跌信息。""" columns = ["name", "description", "close", "change", "change_abs", "volume", "high", "low", "open", "Recommend.All"] return tv_scan(market, [symbol], columns) if __name__ == "__main__": mcp.run()这个文件的核心逻辑其实只有三块:第一块是tv_scan和binance_klines两个Helper,负责真实的数据请求;第二块是几个@mcp.tool()装饰的函数,把数据封装成AI可调用的工具;第三块是mcp.run(),启动Server进程等待Host连接。
我来解释几个关键设计决策。首先,为什么get_klines默认走Binance而不是TradingView?因为TradingView的核心图表数据接口很多需要token或者会话凭证,公共场景下不稳定;而Binance的klins接口是公开的、文档完善、响应快,拿来做K线非常顺手。如果你需要的是美股K线,可以在这个函数里再加一个数据源分支,比如Alpha Vantage或者Yahoo Finance的接口,设计思路一样。
其次,get_technical_analysis用的是Scanner接口的指标列。注意这里有个小坑:Scanner接口返回的数据格式是{"totalCount": n, "data": [{"s": "symbol", "d": [value1, value2, ...]}]},d数组的顺序和你传入的columns顺序一致。所以AI拿到结果后,需要结合"当时请求了哪些列"才能解析每个数值的含义。为了让AI不搞混,我在函数docstring里注明了列的顺序,MCP协议会把docstring一并传给LLM,这是多数AI模型正确理解工具返回结果的关键。
最后,scan_market里的filter_json参数是一个JSON字符串。Scanner接口的过滤条件格式类似{"change": {"gte": 5}},表示涨幅大于等于5%。因为MCP工具参数要求是基本类型,所以这里用JSON字符串传递,在代码里json.loads解析。这也是写MCP Server时常见的一个设计模式:复杂结构用JSON字符串传参。
3.3 在Claude Desktop/Cursor/Codex中注册使用
Server写好后,接下来就是让AI宿主认识它。不同Host的MCP配置方式大同小异,核心都是一个JSON配置里声明"命令+参数"。
以Claude Desktop为例,配置文件在claude_desktop_config.json里,追加一个mcpServers节点:
{ "mcpServers": { "tradingview-mcp": { "command": "python", "args": ["/absolute/path/to/tv_mcp.py"] } } }注意,这里command必须指向虚拟环境里的python解释器路径,比如/path/to/.venv/bin/python,否则可能找不到fastmcp模块。我在这一步耽误了不少时间,希望你能避开。
Cursor的配置方式是打开Settings -> MCP -> Add new MCP server,同样填command和args。配置完成后,Cursor的Agent面板里会多出tradingview-mcp的工具列表,你可以直接在对话里让Agent调用。Codex的话,社区热词里很多人问"codex配置mcp",实际上OpenAI Codex CLI支持在配置文件中声明mcp servers,Node和Python SDK都支持stdio传输,配置思路和Claude Desktop基本一致。
配置好之后,建议先用一个简单的工具测试连通性。在对话里问AI:"tradingview-mcp有哪些工具?"如果返回了工具列表,说明通信正常;如果报错,优先检查MCP Server是否真的能独立运行。验证方法是在终端直接执行:
python tv_mcp.py如果正常启动,你会看到进程挂起等待MCP连接。如果这里直接报错,先解决依赖或语法问题,再回Host重试。
3.4 进阶:用Playwright MCP控制真实图表界面
API直连方案搞定了"数据",但有些场景还必须上"界面"。比如你想让AI截一张当前BTCUSDT的日线图、标注出最近的支撑位,或者你想让AI在图表上应用一个复杂的画线模板,这些操作没有公开API,必须走浏览器自动化。热词里反复出现的playwright mcp就是干这个的。
我的做法是把Playwright MCP作为一个独立的MCP Server注册到Host里,通过两个Server协同工作。tradingview-mcp负责数据查询,Playwright MCP负责操作网页版TradingView。配置方式是在同一个claude_desktop_config.json里声明两个Server:
{ "mcpServers": { "tradingview-mcp": { "command": "python", "args": ["/path/to/tv_mcp.py"] }, "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }启动之后,你可以给AI这样的指令:"打开TradingView图表,把BTCUSDT切到4小时周期,然后截个图发给我分析"。Playwright MCP会驱动真实浏览器打开页面、点击交易对搜索框、输入品种代码、选择周期、操作完成后调用浏览器截图工具把画面返回给AI。这套链路跑通之后,"AI看图做技术分析"就不再是玩具Demo了,而是真能在日常盯盘里用起来的工具。
不过要提醒一下,网页版TradingView的DOM结构是会变的,新的弹窗、新的按钮位置都可能导致自动化脚本失效。我的建议是把"常用操作"封装成Playwright MCP里的自定义脚本,不要让它自由发挥,否则很可能点错按钮。这个度要掌握好。
4. 常见问题与排查技巧实录
4.1 MCP连接不上、超时的排查流程
我在搭建过程中遇到最多的问题就是"Host里看到工具列表,但一调用就超时"或者"MCP Server连接失败"。这类问题有一个固定的排查顺序:
第一步,看Server能不能独立跑起来。直接在终端运行python tv_mcp.py,如果秒退,通常是有语法错误或者依赖没装全,把报错信息看清楚。第二步,确认Host调用的python路径对不对。Claude Desktop这类GUI应用在macOS下经常找不到虚拟环境的python,一定要用绝对路径。第三步,看超时时间。热词里提到"codex timed out after 30 seconds",这个我遇到过,MCP默认超时设置比较短,如果Host机器性能差或者数据拉取慢,很容易触发超时。解决方法是调大Host侧的超时配置,或者在MCP Server内部把耗时操作做缓存,减少重复请求。
我额外加了一个小技巧:在get_technical_analysis这类函数里加一个简单的内存缓存,同标的同参数10秒内不重复请求,能显著减少超时问题,也避免频繁打外部接口被限流。
| 现象 | 可能原因 | 排查操作 |
|---|---|---|
| Host提示MCP Server连接失败 | Python路径错误或依赖缺失 | 终端手动运行python tv_mcp.py验证 |
| 调用工具超时(30秒) | 首次加载模型耗时+网络请求慢 | 调大Host超时配置,或加缓存 |
| Server能启动但工具调用报401 | 数据源接口需要鉴权或限流 | 切换备用数据源,如Binance |
4.2 数据源不可用、行情对不上的处理
数据源接口有时候会抽风,这是做任何数据类项目都躲不开的问题。TradingView Scanner接口偶尔会返回空数据或者403,Binance的公共接口在某些地区网络环境下也可能不稳定。我的应对策略是"多数据源降级":在工具函数里做异常捕获,如果主数据源失败,自动切到备用源。
另外,行情对不上还有一个常见原因是交易对命名不统一。TradingView里BTCUSDT可能写作BINANCE:BTCUSDT或BITSTAMP:BTCUSD,Binance API里则直接叫BTCUSDT。所以我在search_symbols和get_klines里做了标准化:要求用户传入不带交易所前缀的裸代码,然后在函数内部根据目标数据源补全前缀。这样AI理解起来简单,代码也干净。实测下来,让AI自己猜前缀是最容易出错的,尽量在设计工具参数时就消除这种歧义。
4.3 网页版不稳定的替代方案
热词里"tradingview国内用不了了吗"这个问题,与其讨论网络层面的原因,不如从工程上把它解决。我从实际经验出发,核心思路是:不要让核心功能依赖任何单一的远程网页服务。具体做了三件事:
第一,K线数据默认走有公共API的交易所接口,这类接口有多个可用域名,选一个连通性好的即可。第二,TradingView图表库本地化集成,用npm的lightweight-charts在本地渲染图表,保证"看图表"这个核心操作不依赖远程网站。第三,把技术指标计算做本地兜底,如果Scanner接口不可用,可以用本地代码基于K线数据计算RSI、MACD、均线这些常见指标,无非是几个数学公式的事。
这套"API网关+本地图表+本地指标计算"的组合下来,整个tradingview-mcp对任何单一外部服务的依赖都降到了最低,稳定性自然就上来了。
4.4 MCP多Host复用的注意事项
一个tradingview-mcp Server默认只服务一个Host进程。如果你同时用Claude Desktop和Cursor,最好分别启动两个Server进程,或者用SSE(Server-Sent Events)模式把Server跑成HTTP服务,多个Host共用。
我实际用下来,stdio模式最省心,每个Host一个独立进程,互不干扰。如果一定要做HTTP服务,FastMCP也支持,把最后一行改成mcp.run(transport="sse", host="127.0.0.1", port=8000),然后在Host配置里把command/args换成url形式。不过这个方案引入的网络配置会多一些,日常本地用不推荐。
还有一个小细节:如果你在多个项目里同时用MCP,注意给每个Server起不同的名字,否则Host会混淆。
5. 从能用走向好用:进阶方向与个人体会
5.1 扩展方向:策略回测、条件告警、组合监控
tradingview-mcp跑通基础链路之后,可以扩展的方向很多。我目前在用的是三个:策略回测、条件筛选、组合监控。
策略回测的思路是:让AI拿K线数据,配合自己写的策略逻辑,在本地批量计算收益曲线。过去这个过程要手动导出数据、写脚本、反复调整参数,现在直接把需求描述给AI,AI自动调get_klines拿数据、写回测代码、输出结果,效率提升非常明显。条件筛选则是利用scan_market,让AI用自然语言描述筛选条件,比如"市值前50的加密货币里,RSI小于30且成交量大于均线的有哪些",AI会转换成Scanner过滤条件直接扫全市场。组合监控则是定时任务配合MCP工具,让AI每天收盘后拉取持仓品种的技术指标,生成一份摘要报告。
这些扩展本质上都是在"数据工具"之上叠加"AI推理能力",MCP的价值就在于把数据工具变成了AI可自由调用的积木。
5.2 接入流程中的几点经验
回看整个搭建过程,有几个经验值得单独拎出来说。
第一,MCP工具的参数设计决定了AI的上限。如果你的工具函数参数含义模糊、命名不直观,AI很容易传错值。我建议每个工具函数的docstring都写清楚参数含义和可选值,甚至给一个示例调用。第二,返回数据结构要自描述。Scanner接口返回的数组列顺序如果不对应清晰说明,AI解析时会懵。我在字段层面重新封装了一层,让每个返回JSON都带字段名而不是裸数组。第三,日志必不可少。MCP Server默认日志不输出到Host界面,调试时很容易两眼一抹黑。我加了--debug参数开关,开发阶段在终端打印每次请求的URL和响应状态,问题定位速度快很多。
5.3 一些踩坑后的心得
最后聊聊我个人的体会。起初我以为tradingview-mcp最难的部分是写MCP Server——毕竟MCP协议听起来很高端。实际上手之后发现,FastMCP把协议层简化得只剩一个装饰器,真正的难点反而在数据源设计:怎么把TradingView的接口能力、公共API的稳定性、本地计算的兜底三者结合好。
另外,AI工具链的配合远比单点工具重要。tradingview-mcp和playwright mcp、记忆相关的能力组合起来,才真正像是一个能干活的分析师。单靠一个数据工具,AI顶多是个"数据库查询器",而一旦它既会查数据、又会看图、还能记住上下文,工作流就完全不一样了。
在写策略或者盯盘的朋友,如果手头有AI编程工具,我强烈建议花一个下午把这个项目搭起来。这个过程本身也是理解MCP体系最好的实战演练,毕竟看一百篇教程,不如亲手跑通一个Server,让AI帮你拉一次K线来得实在。