首页 / 资讯中心 / 文章详情

Python量化入门:用同花顺iFinD免费接口拉取数据并实现双均线策略

Python量化入门:用同花顺iFinD免费接口拉取数据并实现双均线策略 ★ FEATURED ARTICLE
我见过太多人学 Python 量化笔记本上装好了 pandas背熟了金叉死叉结果在“拉数据”这一步卡了整整一个周末。这不是夸张——数据接口申请要资质免费源要么缺字段要么断更新好不容易调通一个接口返回的 JSON 又和教材里的 DataFrame 对不上。同花顺 iFinD 数据接口免费版恰好把这个问题解决得很舒服注册有免费额度A 股行情、财务指标、交易日历都能通过 Python 直接拉返回结构也相对规整。今天这篇文章我就把从申请账号、安装 SDK、拉取行情到用真实数据跑一个双均线策略的完整流程拆开讲清楚。目标是让刚起步的量化新手在半小时内把真实行情数据装进自己的 DataFrame 里。1. 为什么说量化第一步卡在数据以及同花顺iFinD免费版能解决什么1.1 大多数人学量化不是卡在策略是卡在数据源很多量化教程默认你已经有数据了。书里写“载入上证指数的日线数据”一句话带过但你真的去找的时候会发现选择非常尴尬。先说自己爬。用爬虫抓东方财富、新浪财经的接口能拿到当日数据但历史数据要翻页、要拼接、要处理反爬而且爬下来的数据结构你还要花大量时间清洗。更麻烦的是财务数据、交易日历、复权因子这些“周边数据”爬虫很难覆盖全面。再说免费开源库。Tushare 和 AkShare 确实好用数据覆盖面也不错但 Tushare Pro 很多高质量接口有积分门槛AkShare 有些字段靠解析网页得到偶尔接口变了就要等维护者更新。对于只是想验证一个策略逻辑的个人用户来说能用但总有种“借来的数据不踏实”的感觉。最后说专业终端。Wind、Choice、iFinD 付费版一个终端授权一年几万块个人用户基本不用想。但数据质量、字段丰富度、接口稳定性确实是一分钱一分货。1.2 常见免费数据源的短板对比我把自己用过的几个方案放在一起做了个对比不捧不踩纯粹从“个人量化研究能不能省心”的角度看数据源成本/门槛覆盖品种字段完整度主要痛点AkShare免费pip安装A股、基金、期货等中上部分接口依赖网页解析偶尔失效Tushare Pro免费但有积分门槛A股为主中上高频/财务接口需要积分新手要攒积分自写爬虫免费但费时取决于自己写不可控维护成本高容易踩反爬同花顺iFinD免费版注册即可有免费额度A股、基金等较高调用频率限制需按官方文档规范使用这张表不是劝你放弃其他方案。我的看法是新手阶段最重要的是“快速拿到规范数据把策略逻辑跑通”而不是先在数据采集上耗尽耐心。iFinD 免费版在这一点的定位很准——它把专业终端的数据能力开放了一部分给个人用户让你用接近专业的数据结构做研究又不用掏专业版的钱。1.3 iFinD免费版到底给了什么东西我实际用下来的感受是它给你的不是“阉割版玩具”而是三样很实在的能力第一规范的历史 K 线数据。日线、周线、月线、分钟线都能拿支持前复权、后复权、不复权三种模式。字段基本和主流量化框架对齐open、high、low、close、volume、amount 这些都有。第二基础财务数据和指标。PE、PB、ROE、净利润增速这些常见选股指标可以通过接口按报告期取不用自己爬公告整理。第三交易日历和代码识别。哪些天开市、哪些股票代码目前有效都能直接查。别小看这个自己爬数据的人最烦的就是节假日对齐和退市股票处理。当然免费版也有它的边界比如调用频率、数据范围、字段深度都有限制。这个我在第六部分专门展开先不在这里浪费时间。2. 免费版账号申请与环境准备从注册到第一行代码2.1 注册账号的几个实操细节打开同花顺官网找到 iFinD 相关页面入口一般叫“iFinD数据接口”或“智能金融终端”。进去之后用手机号注册注册时选择“个人”身份即可。这里有几个容易踩的坑我逐一说明注册时如果要求填写机构/公司信息个人用户填“个人研究”或“自由职业”一般没问题不需要伪造企业资质。审核时间通常在 1 到 2 个工作日。别在周五下午提交不然要等到下周一。审核通过后你的账号会绑定一个手机号。登录接口时要用的用户名可能是手机号也可能是网页端设置的自定义用户名以邮件通知为准。免费版通常会有每日数据调用次数的限制。注册后先去官方帮助文档翻一翻最新的限额说明避免脚本跑到一半被限制。这些细节看似琐碎但我见过太多人在第一步就栽了用别人分享的账号跑通了一两次后续全部连接失败还以为是代码问题其实是账号本身没有权限。2.2 安装Python环境与iFinDPy SDK数据接口的 Python SDK 叫 iFinDPy同花顺官方维护直接 pip 安装即可。我用的是 Python 3.10实测没问题。如果你电脑上还没装 Python建议直接装 Anaconda里面自带 pandas、numpy 这些量化常用库省去后面一堆麻烦。# 创建独立环境避免依赖冲突 conda create -n quant python3.10 conda activate quant # 安装核心库 pip install pandas numpy # 安装同花顺数据接口SDK pip install iFinDPy如果公司网络或学校网络有限制pip 下载慢可以换成国内镜像源pip install iFinDPy -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后验证一下能不能正常导入import iFinDPy as ths print(ths.__version__)能打印出版本号说明 SDK 基本就位了。如果这里报错大概率是 Python 版本太低或太高iFinDPy 对 3.6 以下和 3.12 以上的支持都不太好建议用 3.8 到 3.11 之间的版本。2.3 登录与鉴权最容易忽略的坑SDK 装好了下一步是登录。iFinD 的 Python 接口登录方式和网页端不同它不需要你打开终端客户端直接用账号密码在代码里初始化会话。import iFinDPy as ths # 用户名密码换成你自己的 res ths.Py(iFinDUseryour_username, iFinDPwdyour_password) if res 0: print(登录成功) else: print(登录失败错误码, res)返回值是 0 代表成功非 0 就是失败。常见的错误码和含义如下错误码常见原因非0具体看文档用户名或密码错误认证超时当天调用次数超限网络错误局域网代理拦截了请求这里有一个建议密码不要硬编码在脚本里。你后来可能会把这个脚本分享给别人或者推到 GitHub 上一旦密码泄露账号被限制就非常麻烦。我是把用户名密码放在环境变量里的import os user os.environ.get(IFIND_USER) pwd os.environ.get(IFIND_PWD)Windows 下用 setLinux/macOS 下用 export 设置环境变量然后代码里直接读取既方便又安全。2.4 验证连通性拉一只股票试试初次登录成功后别急着上来就写完整策略先拉一只股票的最新行情确认整条链路是通的# 000001是平安银行SZ是深圳交易所 quote ths.HQ_GetRealTime(000001.SZ) print(quote)如果返回结果里有价格、涨跌幅、成交量等信息恭喜你数据链路已经打通了。这条链路打通意味着你从“学 Python 语法”正式跨到了“用 Python 做量化研究”这一步后续所有策略代码都建立在它之上。3. 核心数据接口实操实时行情、历史K线、财务数据3.1 实时行情接口先看懂返回结构HQ_GetRealTime 是我用的比较多的一个接口它返回单只股票的快照数据。虽然个人量化研究更多用历史数据做回测但在实盘盯盘、监控价格触发信号时这个接口非常有用。返回的数据结构一般是列表套字典取出来的样子类似{ code: 0, data: [ { code: 000001.SZ, name: 平安银行, last: 10.85, pct: 1.21, volume: 532198, amount: 573429183 } ] }你不需要手动去翻字段名可以先打印一下返回结果确认实际字段。这里要提醒新手一点不同接口返回字段大小写可能不一致有的叫 volume有的叫 turnoverVolume建议每次都先打印一次再写解析逻辑别凭记忆硬编码。3.2 历史K线接口参数说明与时间周期做策略回测最核心的是历史 K 线。iFinD 的 K 线接口调用方式如下# 返回平安银行从2022-01-01到2023-12-31的日K线后复权 kline ths.HQ_GetKData( iFinDCode000001.SZ, iPeriodD, iStartDate2022-01-01, iEndDate2023-12-31, iMaxCount500, iType2, # 1不复权 2后复权 3前复权 options )iPeriod 参数决定K线周期常用值参数值含义D日线W周线M月线1M / 5M / 15M1分钟/5分钟/15分钟线iMaxCount 是最大返回条数做长周期回测时注意别被这个参数卡住比如你想取十年日线大约 2400 条就必须把 iMaxCount 设到 3000 以上否则返回的数据会被截断。这里有一个我踩过的坑iStartDate 和 iEndDate 表示的是“自然时间范围”如果股票在这期间停牌停牌日不会返回数据行。这意味着你拿到的 DataFrame 时间轴是不连续的做策略时如果要算“持有天数”必须用交易日历对齐不能直接数行数。交易日历接口后面会讲到。3.3 财务数据与交易日历被很多人忽略的两类接口财务数据是选股策略的基础。比如我想取平安银行最近几个报告期的 ROE 和净利润# 以SDK帮助文档为准实现路径是用财务指标接口 fin ths.THS_BasicData( 000001.SZ, endDate,netProfit,roe, , 2017-01-01, 2023-12-31 )需要说明的是iFinDPy 不同版本的函数名和参数顺序偶尔有调整。我自己的做法是装好 SDK 后先看一眼官方帮助文档再跑上述代码。代码里的字段名 endDate、netProfit、roe 是通用的指标字段实际以你本版本支持的字段为准。交易日历接口也值得专门提一下。它解决的核心问题是判断某一天是不是交易日以及拿到两个日期之间的所有交易日期列表。拿到交易日列表你的回测日期循环才能写准确不会把周末和节假日算进去。# 获取2023年所有交易日 trade_dates ths.THS_GetTradeDate(2023-01-01, 2023-12-31)3.4 返回格式与超时处理iFinD 接口的返回基本都是统一格式外层是一个 code0 表示成功非 0 表示失败data 部分是具体内容。写代码时一定要先判断 code不要直接假设调用成功。调用频率上免费版有明确限制。我的经验是循环取多只股票时每调一次接口就 sleep 0.5 到 1 秒避免触发限流。这个习惯非常管用我后来用它拉全市场股票数据时几乎没有因为频率问题被中断过。import time codes [000001.SZ, 600000.SH, 000002.SZ] for code in codes: kline ths.HQ_GetKData(code, D, 2023-01-01, 2023-12-31, 300, 2, ) # 处理数据... time.sleep(0.8) # 关键控制频率4. 从接口数据到DataFrame做量化分析前的标准动作4.1 为什么说“拿到数据”和“能用数据”是两回事新手最容易忽略的一点接口返回的数据并不能直接喂给 pandas。你如果直接 pd.DataFrame(kline[data])生成的表在类型、列名、索引上都可能不满足后续计算的要求。以我拿到的一段 K 线数据为例原始返回通常是这个结构{ code: 0, data: [ { time: 2023-01-03, open: 14.2, high: 14.4, low: 14.1, close: 14.3, volume: 650000, amount: 93000000 }, # ... ] }直接转成 DataFrame 后time 是字符串open 这类字段可能是字符串也可能是浮点而且还可能混杂着 None。如果不做类型转换后面算均线、算收益率都会报错或者得到错误结果。这一步不是多余的洁癖而是量化分析的“标准动作”。4.2 数据清洗的四个必要步骤我总结了一套固定的清洗流程每次拉完数据都走一遍几乎不会出错第一步把 data 字段转成 DataFrameimport pandas as pd raw kline[data] df pd.DataFrame(raw)第二步列名统一为小写df.columns [col.lower() for col in df.columns]第三步把时间列转成 datetime 并设为索引df[time] pd.to_datetime(df[time]) df.set_index(time, inplaceTrue)第四步数值列统一转成 float并处理空值for col in [open, high, low, close, volume, amount]: df[col] pd.to_numeric(df[col], errorscoerce) df df.dropna(subset[close])这一步做完你的数据才能参与任何策略计算。很多人拿到数据后第一版策略结果各种报错其实 80% 的原因是清洗没做干净。4.3 复权模式的选择回测不准的隐形杀手关于复权我必须多说几句。股票分红送股后价格会留下跳空缺口如果你用不复权数据做回测会凭空多出很多“假亏损”。举一个简单的例子某股票 100 元10 送 10 后价格变成 50 元。如果你不做复权处理策略会检测到一根大阴线然后触发卖出信号而实际上你的持股数量翻倍了总资产并没有变化。这就是不复权数据最坑人的地方。我的建议是做中长线回测优先用后复权数据因为后复权是以历史价格为基准当前股价是调整后的数值不会出现现在价格和实盘对不上。做短线技术分析可以用前复权因为它以最新价格为准图形上更接近当前价格水平。别在同一个策略里混用不同复权方式的数据否则指标的可比性会出问题。4.4 本地缓存与增量更新设计免费版有调用次数限制所以本地缓存是必须做的。我自己用的方案很简单历史数据第一次全量拉取后存成 parquet 文件后续每次运行脚本只拉最近几个交易日的数据然后和本地数据拼接。import os # 本地缓存文件路径 cache_path ./data/000001.SZ.parquet if os.path.exists(cache_path): # 读本地数据只补充最新数据 local pd.read_parquet(cache_path) latest_day local.index.max().strftime(%Y-%m-%d) new_data ths.HQ_GetKData(000001.SZ, D, latest_day, 2023-12-31, 10, 2, ) new_df pd.DataFrame(new_data[data]) # ...清洗... combined pd.concat([local, new_df]) combined combined[~combined.index.duplicated(keeplast)] combined.sort_index().to_parquet(cache_path) else: # 第一次全量拉取 kline ths.HQ_GetKData(000001.SZ, D, 2020-01-01, 2023-12-31, 2000, 2, ) df pd.DataFrame(kline[data]) # ...清洗... df.sort_index().to_parquet(cache_path)这个方案做一次后面每次跑策略都快很多还能节省宝贵的接口调用次数。5. 用真实逻辑跑一个双均线策略完整代码与回测解读5.1 为什么首选的入门策略是双均线数据链路通了下一步就是跑通第一个策略。我强烈建议新手首选双均线而不是一上来就写多因子、机器学习。原因很简单第一双均线逻辑足够直观5日均线上穿20日均线买入下穿卖出任何人都能看懂。 第二它刚好能验证你前面所有数据处理的正确性。如果均线计算结果和行情软件对不上说明你的清洗或复权方式有问题。 第三双均线虽然经典但里面包含了未来函数、滑点、手续费等所有真实回测要面对的问题学会处理这些比策略本身更重要。5.2 双均线策略的完整代码下面这段代码我用的是前面的接口和数据清洗流程完整跑通了一个最简单的回测import pandas as pd import numpy as np import iFinDPy as ths # 1. 拉起数据 kline ths.HQ_GetKData( 600000.SH, D, 2020-01-01, 2023-12-31, 2000, 2, # 后复权 ) raw kline[data] df pd.DataFrame(raw) df.columns [col.lower() for col in df.columns] df[time] pd.to_datetime(df[time]) df.set_index(time, inplaceTrue) for col in [open, high, low, close, volume, amount]: df[col] pd.to_numeric(df[col], errorscoerce) df df.dropna(subset[close]) # 2. 计算均线 df[ma5] df[close].rolling(5).mean() df[ma20] df[close].rolling(20).mean() # 3. 生成信号1表示持仓0表示空仓 df[signal] 0 df.loc[df[ma5] df[ma20], signal] 1 # 4. 策略持仓shift是为了避免用到当天收盘才能确认的当日信号 df[position] df[signal].shift(1).fillna(0) # 5. 计算每日收益率 df[market_return] df[close].pct_change().fillna(0) df[strategy_return] df[position] * df[market_return] # 6. 计算净值曲线 df[strategy_nav] (1 df[strategy_return]).cumprod() df[market_nav] (1 df[market_return]).cumprod() # 7. 输出关键指标 total_days len(df) trading_days int((df.index 2020-01-01).sum()) annual_return df[strategy_nav].iloc[-1] ** (252 / trading_days) - 1 sharp_ratio df[strategy_return].mean() / df[strategy_return].std() * np.sqrt(252) print(f策略年化收益: {annual_return:.2%}) print(f市场年化收益: {df[market_nav].iloc[-1] ** (252 / trading_days) - 1:.2%}) print(f夏普比率: {sharp_ratio:.2f}) print(f最大回撤: {(df[strategy_nav].cummax() - df[strategy_nav]).max():.2%})5.3 回测结果怎么解读我跑出来的结果大致是浦发银行在这段时间内双均线策略年化收益比单纯持有略高一点但最大回撤小了不少。这很符合双均线的特性——它在震荡市里会频繁被打脸但在趋势行情里能拿住仓位整体曲线更平滑。不过下面几个坑才是这个示例真正值钱的地方第一个坑是信号偏移。如果你在当天收盘价算出的 ma5 ma20 就立即用当天 close 成交其实引入了未来函数因为收盘后你才能确认信号但确认信号时收盘价已经出来了你只能按第二天的价格成交。所以我在代码里用 position signal.shift(1)这是新手最容易忽略的。第二个坑是手续费和滑点。上面的代码完全没扣手续费而 A 股双边手续费加印花税大约千分之一到千分之二双均线这种频繁换手的策略手续费对最终收益影响很大。真实评估时可以简单地在每次信号变化时扣掉万五trade_cost 0.0005 df[turnover] df[position].diff().abs().fillna(0) df[strategy_return] df[position] * df[market_return] - df[turnover] * trade_cost第三个坑是参数过拟合。我选 5 日和 20 日是因为网上都这么写不代表它对所有股票都有效。你如果把这两条均线参数换成 3 和 10、10 和 30结果可能完全不同。这提醒你策略的价值不在于某一个漂亮的历史回测而在于背后逻辑是否经得起推敲。6. 避坑清单连接失败、限流、免费版边界与合规6.1 连接失败的三种常见原因把这个放最前面因为它最能浪费新手时间。第一种是账号密码错误或者账号没激活。很多人注册后以为马上就能用其实还要等审核审核通过前调用接口返回的错误码你看不懂但其实就是没有权限。第二种是网络代理问题。如果你在公司、学校局域网里代理服务器可能会拦截 iFinD 接口的 HTTPS 请求。排查方法很简单在手机热点下再跑一次登录代码如果手机热点能登录而公司网络不行基本就是代理问题。第三种是接口版本不一致。你在网上搜到一份教程教程用的 SDK 版本是 1.0.x你装的是 2.x函数名或参数个数变了。遇到这种情况最靠谱的做法是打印 SDK 自带的帮助文档而不是凭记忆调函数。6.2 免费版的数据范围与调用频率限制iFinD 免费版不是无限用的。就我实际经验来说它的限制主要体现在几个方面每次调用返回的数据条数有上限超出部分会被截断。单位时间内的调用次数有限制连续高频调用会触发风控。部分深度财务字段可能只对专业版开放免费版只能取到常用指标。应对方式就是前面提到的本地缓存必须做循环之间加 sleep避免不必要的重复调用。只要你不是恶意刷接口正常做研究完全够用。6.3 数据使用的合规边界这一点很容易被忽略但非常重要。通过免费接口拿到的数据适合用于个人学习、研究和策略验证但不建议用来对外提供服务、转售给第三方也不建议在商业产品中直接使用。数据版权属于数据提供商个人研究是一回事商业化是另一回事。另外接口的账号不能共用。你在社区里看到有人分享账号密码用一次两次可能能通但随时可能失效而且如果有人拿账号去刷数据影响的可能是所有人的使用资格。我的建议是老老实实自己去官网注册一个。6.4 我对免费接口使用的一句忠告如果在所有经验里只保留一条我会说先小步跑通再追求复杂。不要想着第一次写代码就把全市场 5000 只股票的因子全部算出来不要想着一步到位搭建一个自动化交易系统。先用一只股票、一段简单均线、一次简单的回测把数据链路和代码流程彻底跑通然后再扩展股票池、增加因子、接入交易接口。我见过不少朋友在数据获取阶段花了两周在策略研究阶段花了两天最后因为一个数据细节没处理对整个回测结果都是错的。反过来把数据基础打好的人后面换任何策略都是复制粘贴的工作量。最后再分享一个小技巧。如果你准备长期做量化研究建议把所有和 iFinD 接口交互的代码封装成一个独立的 data_fetcher 模块所有策略代码只调用这个模块不直接调接口。这样做的好处是以后如果你想换数据源只需要改一个文件而不是把散落各处的 ths 调用全部找出来重写。我自己就是靠这个习惯把从 iFinD 到其他数据源的切换时间控制在了半小时以内。
阅读完成 · 觉得有帮助?
咨询建站