尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

量化交易入门:用同花顺iFinD免费版Python接口搞定数据获取与策略回测

量化交易入门:用同花顺iFinD免费版Python接口搞定数据获取与策略回测 做量化交易的人应该都有体会很多人不是死在策略上而是死在了数据上。想写个双均线试试结果连“今天这只股票收盘价是多少”都拿不到想去核对一个财务指标被各种数据源的字段搞到头大。我当初踩过一圈坑之后最终把数据通道固定在了同花顺的iFinD接口上尤其是免费版对个人学习来说真的是低成本入门的正路。这篇文章会围绕同花顺iFinD免费版的数据接口把从环境准备、账号认证、核心接口调用、数据落地到第一个能跑通的量化策略完整讲一遍。适合刚接触Python、想尝试量化交易但被数据源卡住的朋友也适合已经在用其他数据源、想对比或者增加一条稳定备选通道的人。我会把实际操作中遇到的坑、权限的边界、频率的问题一并说清楚尽量让你少走我当初走过的弯路。1. 项目设计与思路拆解为什么第一条数据通道我选iFinD1.1 量化交易的数据基石你真正需要的是什么数据很多新手在开始量化时首先想到的是“我要写什么策略”但真到了动手那一步会发现策略代码不过几十行数据清洗和获取却能占掉你80%的时间。这里先量化一下我们到底需要哪些数据行情数据日线、分钟线、盘口快照里面又涉及前复权、后复权、不复权这些细节。做回测如果复权处理错了结果根本没法看。财务数据利润表、资产负债表、现金流量表还有各种派生指标。基本面选股、排雷都依赖这部分。基础信息股票代码、行业分类、上市日期、停复牌状态。这些都是做股票池筛选的地基。所以我在设计整个流程时第一个想法就是数据接口一定要统一。我不希望行情从一个数据源拿、财务从另一个数据源拿、交易日历又从第三个源拿最后光是对齐数据就够崩溃的。iFinD免费版的价值就在这里它是一个相对完整的一体化数据接口行情、财务、宏观、板块这些都能从一个SDK里取到省掉了非常多的对接成本。1.2 数据源选型对比免费数据接口有哪些凭什么选iFinD我在动手之前把市面上的免费Python数据接口大概都摸了一遍简单做个对比数据源免费额度数据范围接口风格我的评价Tushare Pro注册送积分积分决定权限行情、财务、宏观都覆盖需要token调HTTP接口数据全但高权限字段需要攒积分AkShare完全免费覆盖面极广但来源杂乱直接pip安装调用学爬虫可以做数据校验要小心Baostock完全免费以行情数据为主Python SDK胜在稳定但财务数据偏少同花顺iFinD免费版注册后满足个人学习场景行情、财务、板块都覆盖iFinDPy官方SDK与行情终端的同源数据质量稳定我最终把主要通道放在iFinD上原因有几点第一它是同花顺官方出的Python SDK字段定义、数据质量跟同花顺客户端里看到的东西是同一套体系可信度比较高第二它有免费版个人学习足够用不用一上来就面对付费墙第三社区里用的人多遇到问题搜一下基本都有答案这点对新手非常重要。不过也要说句公道话没有任何一个免费数据源是全能的。我现在的做法是“主备并行”主力用iFinD取行情和财务另一套免费源做交叉校验尤其是遇到明显异常值的时候两边对一下基本能判断是哪边的数据出了问题。1.3 整体方案设计从接口到策略的最小闭环在写任何代码之前我先画了一个最小闭环的方案方向是先跑通再扩展第一步Python环境搭建 iFinDPy安装。第二步注册iFinD账号验证登录与连接。第三步调用接口获取一只股票的日线行情落地成CSV。第四步基于这份数据写一个最简单的双均线策略做一次像样的回测。第五步把获取财务数据的接口也打通为后续选股留好接口位。这么设计的原因很简单最小闭环里每一个环节都在为下一步铺路。如果一上来就想把全市场5000只股票的基本面、分钟线全部拉下来大概率会被权限、频率限制打回原形。先跑通单只股票、单个策略让整条链路不再有未知数再考虑扩展这个节奏对新手来说最友好。2. 环境准备与接口认知动手前必须搞清楚的几个细节2.1 Python环境搭建选对版本比装新版本更重要iFinDPy这个SDK对Python版本是有要求的我实测下来Python 3.8到3.11之间都比较稳装最新版Python之前最好先看一眼SDK的官方说明避免出现底层依赖库编译失败的情况。安装方式很简单直接用pippip install iFinDPy如果下载速度慢可以用国内镜像源pip install iFinDPy -i https://pypi.tuna.tsinghua.edu.cn/simple装完之后在Python里执行一下import iFinDPy如果不报错环境基本就通了。这里特别提醒Windows用户如果是在系统自带终端里装尽量用管理员身份打开命令提示符如果提示pip不是内部命令大概率是安装Python时没有勾选“Add Python to PATH”这是新手阶段最常见的坑。至于编辑器我推荐VSCode或者PyCharm都可以。如果是在VSCode里建一个项目文件夹在终端里执行python -m venv venv创建虚拟环境再选择该环境作为解释器能让不同项目的依赖相互隔离省得日后再为各种包的版本冲突头疼。2.2 iFinD账号与免费版权限登录认证要摸清楚iFinD的接口走的是账号认证体系不是简单的token字符串。官方SDK提供了一个登录接口通常是iFinDLogin传入你的同花顺账号和密码。我第一次用的时候以为像其他接口那样直接填token就行结果一直登录失败后来仔细看了一下文档才知道需要调登录方法账号和密码是必须的。免费版的权限边界需要提前心里有数它允许调用一部分常规的行情和财务数据但对一些高频数据、部分高频字段、特定板块数据是有限制的。遇到取不出来的字段接口通常会返回一个空值或者报错这个在后面的常见问题里我会详细说。2.3 认识iFinD的代码体系股票代码的“身份证”调用行情接口之前要先把代码规则搞清楚。A股股票的代码在iFinD接口里一般会带上交易所后缀深市股票带.SZ沪市股票带.SH北交所股票带.BJ。比如平安银行是000001.SZ贵州茅台是600519.SH。这看起来是个小细节但害的人不少。我见过太多人传了裸代码000001结果返回空列表调试半天不知道问题出在哪。除了股票代码指数、板块、期货的编码规则也各不相同建议写代码之前先把要用到的代码格式列出来统一处理能用接口查询的就去查询不要在代码里硬编码。3. 核心接口实操手把手把第一份数据拿到本地3.1 登录与连接测试30秒确认环境可用环境装好之后第一步就是登录。我用的是Windows系统在VSCode的终端里启动Python直接执行from iFinDPy import * import pandas as pd # 替换成你自己的账号密码 login iFinDLogin(你的账号, 你的密码) print(login)如果返回值是0说明登录成功如果非0说明登录失败需要检查账号密码或者网络。这一步是整个流程的“探路石”只要登录通了后面一切的调用就都有了基础。登录成功之后我建议先不急着拉大量数据先做一次轻量级的验证比如获取今天某只股票的实时行情。这样能快速确认账号的数据权限是正常的。3.2 历史行情获取日线数据一次讲透历史行情是量化研究中使用频率最高的数据。iFinD里获取历史行情常用的接口是iFinDHistoricalQuotes以下是我常用的写法# 获取贵州茅台从2023-01-01到2023-12-31的日线数据 quotes iFinDHistoricalQuotes( 600519.SH, open,high,low,close,volume,amount, 2023-01-01, 2023-12-31, periodD )这里几个参数我分别说一下第一个参数是股票代码必须带后缀。第二个参数是字段列表用逗号分隔。open、high、low、close、volume、amount这六个字段是最常用的“OHLCV成交额”组合。第三个和第四个参数是起止日期。第五个参数periodD表示日线如果要周线可以换成periodW分钟线是period1m或period5m之类的写法。返回的数据结构一般是列表套字典直接看比较费劲我习惯转成DataFramedf pd.DataFrame(quotes) print(df.head())转出来之后你会发现字段名可能带有代码前缀那就是SDK故意这么设计的方便你在同时取多只股票时区分。如果不喜欢这种长名字可以自己写个清洗函数把首列代码信息拆出来再重命名成简洁的列名。这里再强调一个复权问题。做回测必须用复权价格。不复权的价格在除权除息日会出现跳空均线、收益率计算全都是错的。iFinD接口里一般有复权字段可以在取数时带上adjust_1之类的参数具体字段名不同版本会有差异务必以官方文档为准。3.3 实时行情与快照数据盘中看盘的轻量接口除了历史行情盘中数据也有对应接口比如获取某只股票当前的实时报价。这类接口适合做盘中监控和简单的条件提醒但免费版对实时数据的刷新频率可能有限制不适合做高频交易。我自己的用法是开盘前用它拉一次集合竞价结果盘中偶尔核对一下价格真正做监控还是交给同花顺客户端更省心。3.4 财务数据获取把基本面数据也拉下来财务数据是基本面量化的“弹药库”。iFinD里获取财务数据的接口一般是iFinDGetFinancialData一类可以获取营业收入、净利润、资产负债率等指标。我的写法大概是这样# 获取贵州茅台最近4个报告期的净利润单位元 fin_data iFinDGetFinancialData( 600519.SH, REVENUE,NETPROFIT, 2022-12-31, 2023-12-31, periodY )这里REVENUE、NETPROFIT是财务指标的编码不同指标对应不同编码建议先去官方文档或者接口的指标列表里查清楚不要靠猜。财务数据和行情数据在数据结构上有明显的不同行情数据是等间隔的时间序列财务数据是按报告期分布的做数据处理的时候要特别注意对齐逻辑比如把财务数据按报告期往前填充到每一天才能与日线行情做联合计算。3.5 数据落地从接口到CSV/DataFrame的规范姿势数据拿到手之后如果不落地下次运行还要重新请求既慢又容易被频率限制。我一般的做法是df.to_csv(600519_daily.csv, indexFalse)再读的时候直接df pd.read_csv(600519_daily.csv, parse_dates[time])这里一个小建议落地文件命名为“代码_数据类型_起止日期.csv”比如600519_daily_20230101_20231231.csv。这样文件名本身就是索引时间久了也不会混淆。数据量大了以后可以改用数据库但对个人学习来说CSV足够用等你有天发现自己每天要跑几十只股票的时候再升级到SQLite或者PostgreSQL也不迟。4. 量化策略初体验拿到数据后做什么4.1 一个能跑通的双均线策略骨架数据通了的最终目标是为了跑策略。这里我给出一个极简的双均线策略骨架用黄金交叉和死亡交叉产生买卖信号然后计算策略收益。import pandas as pd import numpy as np # 读取刚才保存的行情数据 df pd.read_csv(600519_daily_20230101_20231231.csv, parse_dates[time]) df df.sort_values(time) # 计算5日均线和20日均线 df[ma5] df[close].rolling(5).mean() df[ma20] df[close].rolling(20).mean() # 生成信号MA5上穿MA20为买入下穿为卖出 df[signal] 0 df.loc[df[ma5] df[ma20], signal] 1 df[position] df[signal].diff() # 计算每日收益率 df[ret] df[close].pct_change() df[strategy_ret] df[ret] * df[signal].shift(1) # 累计收益 df[cum_ret] (1 df[strategy_ret]).cumprod() print(df[[time, close, ma5, ma20, signal, cum_ret]].dropna())这个策略骨架虽然简单但它包含了一个量化策略的完整要素数据准备、因子计算、信号生成、收益核算。运行完之后你可以看到策略的累计净值曲线也可以用df[cum_ret].iloc[-1]直接算出这一年下来的累计收益跟买入持有做对比。当然这个策略本身非常稚嫩没有考虑手续费、滑点也没有做参数优化。它的作用不是生产一个“能赚钱的圣杯”而是帮你把“数据→策略→回测”这条路打通。我第一次跑通的时候看到输出表的那一刻才真正感觉到量化原来离自己没那么远。4.2 频率限制与批量获取的工程化建议当你开始拓展到多只股票时频率限制问题就浮出水面了。免费版接口通常对单位时间内的请求次数有限制。我一开始不懂写了个循环批量拉几十只股票结果跑到一半开始报错。后来学乖了处理办法是import time codes [600519.SH, 000001.SZ, 601318.SH] all_data [] for code in codes: try: quotes iFinDHistoricalQuotes(code, open,high,low,close,volume, 2023-01-01, 2023-12-31, periodD) df pd.DataFrame(quotes) all_data.append(df) print(f{code} done) except Exception as e: print(f{code} error: {e}) time.sleep(1) # 主动限速避免触发频率限制这里的sleep(1)看起来笨拙但非常有效。我试过调整为sleep(0.5)成功率明显下降调到1秒之后就稳定多了。等以后对接口更熟悉了可以根据返回码动态调整请求速度但在入门阶段宁可慢一点也不要被封。5. 常见问题与排查技巧实录5.1 问题速查表我在使用iFinD免费版接口的过程中遇到了不少问题整理成一个速查表建议直接收藏现象可能原因解决思路登录返回非0账号密码错误、网络问题检查账号密码确认网络能访问同花顺服务器获取行情返回空列表股票代码没带后缀检查代码是否带.SZ、.SH、.BJ后缀某些日期数据缺失股票停牌、节假日用交易日历接口对齐不要用自然日请求频繁被限单位时间请求次数过多循环里加sleep拉长间隔财务数据字段返回NaN免费版权限不足换一个相近字段试试或者人工核对接口突然需要重新登录登录态过期写个重试逻辑检测到非0自动重新登录CSV日期读取成字符串没有指定parse_dates读入时指定parse_dates[time]5.2 免费版最容易踩的3个坑第一个坑是代码后缀问题。这个我在前面反复强调过因为踩的人实在太多。裸代码在客户端里能查但到了Python接口里就必须带后缀否则接口可能直接返回空。我的习惯是维护一个代码后缀的映射表获取数据时统一处理def format_code(raw_code): raw_code str(raw_code).zfill(6) if raw_code.startswith(6): return f{raw_code}.SH elif raw_code.startswith((0, 3)): return f{raw_code}.SZ elif raw_code.startswith((4, 8)): return f{raw_code}.BJ第二个坑是免费版权限的隐性边界。有些字段在文档里写了但调用时返回的东西很少甚至全是NaN。我遇到过取某个财务指标时前几年有数据、最近一期返回空的情况一开始以为是自己代码写错了后来才发现是该字段在免费版里有延迟。遇到这种情况我的建议是先去客户端手动查一下这个字段有没有值如果客户端有而接口没有那基本就是权限问题别跟代码死磕。第三个坑是历史数据里的复权处理。新手做回测最容易忽略这个。如果不复权分红送股在价格上造成的跳空会被策略误判成大涨大跌信号回测结果看着漂亮实盘完全不是一回事。所以取数据时一定要选择复权字段并且默认使用前复权来保持最新价格的真实性。5.3 独家小技巧缓存和日志让数据源稳定一倍最后分享两个比较实用的工程技巧。第一个是本地缓存。我封装了一个小的缓存函数凡是已经取到的数据先查本地CSV存在就直接读不存在才请求接口。对于重复跑策略的场景这个优化可以把时间从几分钟压到几秒钟import os def get_cached_quotes(code, start, end): filename fcache/{code}_{start}_{end}.csv if os.path.exists(filename): return pd.read_csv(filename, parse_dates[time]) quotes iFinDHistoricalQuotes(code, open,high,low,close,volume,amount, start, end, periodD) df pd.DataFrame(quotes) os.makedirs(cache, exist_okTrue) df.to_csv(filename, indexFalse) return df第二个是请求日志。我在取数函数里加了简单的日志输出记录每次请求的股票代码、数据条数和耗时。这样做有两个好处一是你能直观看到哪次请求很慢二是当请求结果不对劲时可以通过日志回溯是哪一步出的问题。说到底同花顺iFinD免费版接口对个人学习者来说是一个非常友好的起点。它把从数据获取到策略验证的链条缩短了让量化交易入门不再是“想学但无处下手”。我个人在实际操作中最大的体会是先别急着追求复杂的策略先把数据通道练到像呼吸一样自然。当你能够随时拿到自己想看的数据、能快速落地成文件、能在一个下午跑通一个策略时量化的门槛对你就已经降下来了。最后再分享一个我一直在用的习惯每次运行策略前先打印一条当前数据的最新日期和最后几条记录确认数据和预期一致后再继续。这两年我因为数据陈旧、数据对不齐翻过几次车每次都是栽在“直接跑不看数据”上。从数据接口到策略模型中间每一个环节都值得认真对待。
返回列表