python量化开发【初级入门】
α 策略:β 是与市场同涨共跌的部分,α 是独立于市场波动以外的部分,具体的做法可以通过做多股票组合(α+β),同时做空股指期货(-β),最终就剩下了绝对收益 α。利润表:净利润率【合同拿到手的钱】、期末现金及现金等价物余额【实际拿到的钱】通过参加股东大会、给企业高管打电话的方式:判断年报是否造假。2、技术面:股票收盘价、K线(日/周/月/年)、均线(5/10/20/60日)1、基本面:居民消费指
一、量化交易:
通过将与股票相关的信息数据化、策略化、并且通过历史数据验证它们的交易逻辑性
我们从全部股票,选出4到5个政策长期相当扶持的行业,这样就差不多剩下1/3股票了,去除一些质地不好的、ST差的,再选出中间主力运作比较活跃的,不是说几年趴着不动的,或波动比较小的,最后剩下1/6只股票,再根据技术面给它一个买点,或者政策面上有什么大的变化,比如资金链放松了,关注股票池里1/6的股票,因此很容易熟悉它们。
二、量化概念
1、基本面:居民消费指数、人均国内生产总值(GDP)、净资产收益率(ROE)
2、技术面:股票收盘价、K线(日/周/月/年)、均线(5/10/20/60日)
三、量化策略
1、赚钱:低买高卖
2、指标:
均线:择时策略
盈利能力:选股策略
周期性:板块轮动策略
四、常见的股票量化指标
1、相关平台:
财经网站:新浪、雅虎、东方财富
证券公司:中信、中金、国信、天风等
炒股平台:同花顺、通达信、大智慧等
2、择时-技术面:
① K线跌入BOLL的下轨买入,突破上轨卖出
② MACD金叉:DIF快速线上穿DEA慢速线
③ 换手率:天量见天价、地量见地价。
绝对地量:小于1%
成交低靡:1%-2%
成交温和:2%-3%
成交活跃:3%-5%
带量:5%-8%
放量:8%-15%
巨量:15%-25%
成交怪异:大于25%
3、选股-基本面:
① 市场宏观环境
② 企业盈利能力
③ 年报数据价值最高,说明事项最多
④ 行业景气度
⑤ 舆情数据
4、找年报地址:巨潮资讯网
最新公告中可以查看公司报告文档
通过参加股东大会、给企业高管打电话的方式:判断年报是否造假
5、用财务数据来选股:
利润表:净利润率【合同拿到手的钱】、期末现金及现金等价物余额【实际拿到的钱】
杜邦分析:净资产收益率
市盈率高:代表大家都很看好它
管理层变动:大股东增持、减持
6、量化策略:
α 盲点套利:β 是与市场同涨共跌的部分,α 是独立于市场波动以外的部分,具体的做法可以通过做多股票组合(α+β),同时做空股指期货(-β),最终就剩下了绝对收益 α。
7、根据市场来选股:
大牛市买小牛股、小牛市买大牛股;
行情火爆买冷门股、行情低迷买热门股;
大盘低位买高位个股,大盘高位买地位个股
8、相对价位CKDP
CKDP 的“0”附近查找低位,“100”高位
9、K线技术指标:
趋势型:移动平均线、简易波动、趋向指标
均线型:移动平均线、指数平滑均线、多空指标
成交量:成交量指标、成交线指标、量平滑移动平均线
其他:成本均线、心理线
五、公募量化策略【基本面】:
1、指数增强:购买的大部分股票基本复制指数的成分股,通过择时、择股等手段,获得比指数更高的收益回报
2、量化选股:通过量化模型选股,在合适的时机买入,追求超越业绩基准的超额收益
3、量化对冲:市场中性,追求的是绝对收益α
4、换仓周期:一个月
六、私募量化策略【技术面】
1、换仓周期:几天
2、高频交易
3、通过高换手率来控制暴露的风险
4、量化策略:期货策略、期权策略、债券策略等
5、期货策略CTA(管理期货)策略:投资范围包括股指期货策略、大宗商品期货策略、国债期货策略,最经典的就是捕捉价格动量趋势,通过快速止损实现“亏小赢大”的局面
6、套利量化策略:通过跨市场、跨期限、跨品种去捕捉市场的不合理价差。
例如国内大商所的大豆、玉米可以和芝加哥期货交易所的农产品(5.960,0.18,3.11%)进行跨市场套利;
豆油、棕榈油、菜籽油互为替代品,受到季节性气候的影响可能会出现跨品种套利空间;
同一品种不同月份的价格强弱变化又可以带来跨期限套利
7、A股量价策略:A股还是以散户交易为主,私募的量化策略可以捕获到散户的不理性行为,反向操作即可赚取超额收益,这几年很受市场追捧,为了挖取超额收益,只能采用更高频的数据。但在相同市场环境。
8、资金容量:相同市场环境下,换手率越高的策略资金容量越小
七、如何搭建量化交易系统
1、量化交易系统的组成:
数据端:
可视化:技术层面的K线图
行情:股票的今天价格
决策端:
交易策略:做决策
执行端:
柜台:执行交易、委托、计算持仓、计算资金、做核对的部分
2、使用Python实现量化交易、
1)Data:
A、指数:
a、持仓个股
b、行情
c、资金流
B、个股:
a、基本信息
b、行情
c、资金流
2)Strategy:
A、择时策略:
a、布林线
b、移动平均线
c、相对强弱指标
B、选股策略:
a、 盈利能力
b、市值
c、估值
3)Trade:
A、委托
B、成交
C、持仓
D、资金
4)Chart
八、量化交易系统的Data模块
1、股票的特性
1)股票:股份公司的所有权凭证、盈亏自负
2)基金:投资组合(股票、债券、现金)
3)债券:还本付息的有价证券(国债、企业债、金融债券)
风险:风险(10%)>基金(5%)>债券(1%)
收益:股票 > 基金 > 债券
九、获取股票数据的2种方式:
1、免费的数据接口:
数据源:天勤量化、BigQuant、JoinQuant(聚宽)等
基本数据:每天的行情、财务数据、技术指标
2、付费的数据接口:
数据源:Wind和彭博
基本数据:提供秒级的行情数据、高阶复杂的技术指标、量化策略
费用:3万
优势:省掉重复造轮子的精力
十、使用JQData查询行情数据
1、数据字典:
股票数据:提供2005年至今沪深A股全面的行情、财务、基本面等数据
行业概念数据:包含行业板块、概念板块数据
指数数据:包含沪深市场多只指数数据
宏观经济数据:包含国内的重要宏观经济数据
期货数据:涵盖中金所、上期所、郑商所和大商所的所有期货合约数据
期权数据:提供股票期权和商品期权的合约资料和行情数据
场内基金数据:包含ETF、LOF、分级基金、货币基金完整的行情、净值数据
场外基金数据:提供场外基金单位净值、复权净值、投资组合等数据
技术分析指标:技术分析指标因子库
Alpha101因子:WorldQuant LLC 发表论文中给出的101个Alphas因子
Alpha191因子:短周期交易型阿尔法因子
聚宽因子库:包含数百个质量、情绪、风险、成长等六大类因子
舆情数据:包含新闻联播等舆情数据
JQData:能在本地调用的全品种量化金融数据
债券数据:提供债券基本信息、国债逆回购、可转债等债券数据
2、聚宽JQData获取所有股市数据
import time
from jqdatasdk import *
auth('XXX','XXX') #账号是申请时所填写的手机号;密码为聚宽官网登录密码
# 将所有股票列表转化成数组
stocks = list(get_all_securities(['stock']).index)
# 长度
print(len(stocks))
# 循环所有股票行情数据
for stock_code in stocks:
df = get_price(stock_code, count=10, end_date='2023-08-31', frequency='daily', panel=False)
print(df)
time.sleep(3)
3、Resample函数
① Python数据分析库Pandas的方法函数
转换时间序列的频次
统计汇总
② 日K ——> 周K
周K开盘价:周一的开盘价
周K收盘价:周五的收盘价
周K最高价:一周中最高的最高价
周K最低价:一周中最低的最低价
③ 统计汇总功能:resample.sum / .count
Sum = 720
④ pd.DataFrame()
是 Pandas(Python 数据分析库)中的一个函数,用于创建数据结构称为 DataFrame。DataFrame 是一个二维的、表格型的数据结构,类似于电子表格或 SQL 表,可以存储和处理各种类型的数据。
⑤ 设置行列不忽略
# 设置行列不忽略
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 10)
⑥ Resample周期转换:通过日K线计算月K线
df = get_price('000001.XSHE', count=7, end_date='2023-08-31', frequency='daily', panel=False) # 获取日K
df['weekday'] = df.index.weekday
# 获取周K(当周的): 开盘价(当周第一天)、收盘价(当周最后一天)、最高价(当周)、最低价(当周)
df_week = pd.DataFrame()
df_week['open'] = df['open'].resample('W').first() # 周K的开盘价
df_week['close'] = df['close'].resample('W').last() # 周K的收盘价
df_week['high'] = df['high'].resample('W').max() # 周K的最高价
df_week['low'] = df['low'].resample('W').min() # 周K的最低价
⑦ Resample汇总统计:统计一下月成交量、成交额(sum)
# 汇总统计: 统计一下月成交量、成交额(sum)
df_week['volume(sum)'] = df['volume'].resample('W').sum() # 周K的成交量
df_week['money(sum)'] = df['money'].resample('W').sum() # 周K的成交额
4、财务指标:
企业财务的构成:
资产负债表:
体现企业家底和负债情况
财务状态:资产、负债、所有者利益
利润表:
公司盈利能力、赚了多少、怎么赚的
隐含着对外来利润增长的预期
体现市场空间、成长能力
经营成果:收入、成本费用、利润
现金流量表【最难造假,需要合同和收付记录】:
权责发生制 vs 收付实现制
体现造血能力、竞争优势、议价优势
现金流入、现金流出
5、财务指标选股找龙头企业、或者蓝筹企业:
eps:每股收益= 净利润/股本数
operating_profit:经营活动净收益 = 营业总收入 - 营业总成本
inc_net_profit_year_on_year:净利润的同比增长率 = 今年的利润 - 去年的利润/去年的利润
inc_net_profit_annual:环比增长率
roe > 15%:净资产收益率ROE(%) = 归属于母公司的2倍净利润 / 归属于母公司的净资产
roa:总资产净利率ROA(%)
net_profit_margin:销售净利率(%)
gross_profit_margin > 75%:销售毛利率(%)
6、财务指标选股:
利用成长增速选股概率性很高(eps每股收益>同行业平均值,roe净资产收益率>同行业平均值,净利润同比增长率>同行业平均值,经营活动净收益>同行业平均值),近3年近5年的roe等指标是排在前列的、未来一年的股价都是增长的,除非说行情市场特别不好、或者个别公司股价已经涨的很高、估值很高的情况,大部分公司股票都是会上涨的
'''获取股票财务指标'''
df = get_fundamentals(query(indicator), statDate='2022') # 获取财务指标数据
# df.to_csv(r'D:\DeltaFQuant\data\finance\finance2022.csv') # 存储数据
# 基于盈利指标选股:eps、operating_profit,roe,inc_net_profit_year_on_year
df = df[(df['eps'] > 0) & (df['operating_profit'] > 973489901) &
(df['roe'] > 10) & (df['inc_net_profit_year_on_year'] > 10)]
print(df)
7、股票方法库
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project :DeltaFQuant
@File :Stock.py
@IDE :PyCharm
@Author :kaiwen.du
@Date :2023/12/12 0012 21:31
'''
import time
import pandas as pd
from jqdatasdk import *
auth('xxx','xxx') #账号是申请时所填写的手机号;密码为聚宽官网登录密码
# 设置行列不忽略
pd.set_option('display.max_rows', 10000)
pd.set_option('display.max_columns', 1000)
'''
# 上海证券交易所 .XSHG '600519.XSHG' 贵州茅台
# 深圳证券交易所 .XSHE '000001.XSHE' 平安银行
'''
def get_stock_list():
'''
获取所有A股股票列表,
上海交易所.XHSG
深圳交易所.XSHE
:return: stock_list
'''
stock_list = list(get_all_securities(['stock']).index)
return stock_list
def get_single_stock_price(code, time_freq ,start_date, end_date):
'''
获取单个股票行情数据
:param code: 股票代码
:param timeperiod: 时间周期
:param stadate: 开始时间
:param endate: 结束时间
:return: df
'''
data = get_price(code, start_date= start_date, end_date=end_date, frequency=time_freq, panel=False)
return data
def export_data(data, filename, type):
'''
导出股票相关数据
:param data: 股票行情数据
:param filename: 文件名
:param type: 股票数据类型,可以是: price、finance
:return:
'''
file_rote = 'D:\DeltaFQuant\data\'' + type + '\'' +filename+'.csv'
data.to_csv(file_rote)
print('已成功存储至:', file_rote)
def transfer_price_freg(data, time_freq):
'''
转换股票行情周期
:param data: 股票行情数据
:param time_freq: 时间周期
'''
df_trans = pd.DataFrame()
df_trans['open'] = data['open'].resample(time_freq).first()
df_trans['close'] = data['close'].resample(time_freq).last()
df_trans['high'] = data['high'].resample(time_freq).max()
df_trans['low'] = data['low'].resample(time_freq).min()
return df_trans
def get_single_finance(code, date, statDate):
'''
获取单个股票财务指标
:param code: 股票代码
:param date: 日期
:return: df
'''
data = get_fundamentals(query(indicator).filter(indicator.code == code), date=date, statDate=statDate) # 获取财务指标数据
return data
def get_single_valuation(code, date, statDate):
'''
获取单个股票估值指标
:param code: 股票代码
:param date: 日期
:return: df
'''
data = get_fundamentals(query(valuation).filter(valuation.code == code), date=date, statDate=statDate) # 获取财务指标数据
return data
十、实战内容
1、调用stock:创建example模块>stock脚本>获取数据
2、实时获取:获取日K数据、循环获更新
import pandas as pd
import data.stock as st
# 初始化变量
code = '000001.XSHE'
# 调用一只股票的行情数据
data = st.get_single_stock_price(code=code, time_freq='daily', start_date='2022-12-01', end_date='2022-12-31')
# 存入csv
st.export_data(data=data, filename=code, type='price')
# 从csv中获取数据
data = st.get_csv_data(code=code, type='price')
print(data)
# 实时更新数据:假设每天更新日K数据 > 存到csv文件里面 > data.to_csv(append)
十二、股票交易规则
1、开户:炒股平台、券商(交易费)
2、交易版面:K线、盘口、交易价格、数量(100股)
3、交易费: 佣金<3%、过户费1元每千股、印花税1%。
4、A股特点: T+1交易、 ±10%(主/中小板)±20%(创业/科创板)
5、计算每日涨跌幅
# 计算每日涨跌幅
def calculate_change_pct(data):
'''
计算每日涨跌幅 = ( 当期收盘价-前期收盘价 ) / 前期收盘价
:param data: dataframe, 带有收盘价
:return: dataframe, 带有涨跌幅
'''
data['close_pct'] = (data['close'] - data['close'].shift(1))\
/ data['close'].shift(1)
return data
十三、计算买入、卖出信号
1、新建Strategy
策略开发、生成交易信号
2、建立周期性选股策略
3、生成交易信号
确定买入、卖出条件
np.where(条件,如果满足,如果不)
strategy.py
def compose_signal(data):
# 整合信号
data['buy_signal'] = np.where((data['buy_signal'] == 1)
& (data['buy_signal'].shift(1) == 1), 0, data['buy_signal'])
# 只要第一次卖出,二次卖出都不算
data['sell_signal'] = np.where((data['sell_signal'] == -1)
& (data['sell_signal'].shift(1) == -1), 0, data['sell_signal'])
data['signal'] = data['buy_signal'] + data['sell_signal']
return data
4、计算持仓收益
总盈亏 = (市价 - 成本价) * 股数
浮动盈亏比 = (市价 - 成本价) / 陈本价
成本价 = 买入金额 / 持有股数
股数 = 累计买入股数
5、计算收益率、计算累计收益率
def calculate_cum_prof(data):
"""
计算累计收益率
:param data: dataframe
:return:
"""
data['cum_profit'] = pd.DataFrame(data['profit_pct'] + 1).cumprod() - 1
return data
def calculate_profit_pct(data):
"""
计算收益率
:param data: data
:return:
"""
data.loc[data['signal'] != 0, 'profit_pct'] = (data['close'] - data['close'].shift(1)) / data['close'].shift(1)
data = data[data['signal'] == -1]
return data
十四、什么是最大回撤:
1、最大回撤:
在选定周期内任意历史时点往后推,产品净值走到最低点时的收益率回撤幅度的最大值
是一个非常重要的风险指标
2、公式:
最大回撤 =(低谷值 - 高峰值) / 高峰值
不会把负数说出来
最大的亏损比例
3、最大回撤价值:
4、计算方式
def calculate_max_drawdown(data):
"""
计算最大回撤比
:param data: dataframe
:return:
"""
# 选取时间周期
window = 252
# 选取时间周期中的最大净值
data['roll_max'] = data['close'].rolling(window, min_periods=1).max()
# 计算当天的回撤比 = (谷值 - 峰值) / 峰值 = 谷值 / 峰值 - 1
data['daily_dd'] = data['close'] / data['roll_max'] - 1.0
# 计算时间周期中的最大回撤比,即最大回撤
data['max_dd'] = data['daily_dd'].rolling(window, min_periods=1).min()
return data
5、计算风险收益指标:夏普比率
夏普指数定义:衡量的是一项投资在对其调整风险后,相对于无风险资产的收益表现
公式:
夏普比率:(期望的投资回报率 - 无风险利率) / 投资回报率标准差
解释:无风险利率:例如国债年化3%左右
投资回报率标准差 = 一种离散指标,体现数据样本内部的差异性
投资回报率标准差 = | 每一项数据项 - 均值 |²的总和 / 数据项个数
意义:投资者额外承受的每一单位风险所获得的额外收益:标准差、波动、风险
比较方式:越好越好,收益远高于风险
十五、如何筛选基金
(一)3个基本维度:3-5年业绩(收益)、基金经理、风险指标(最大回撤、夏普、波动)
(二)选基金流程:
1、热门主题进入:选2只你看好行业的基金、1只灵活配置各行各业都有、1只指数基金例如沪深300等
2、行业筛选:离民生近的、你看得懂的(例如:食品、饮料、医疗行业、新能源)
3、选近3年的长期收益排序、在排序近2年、近1年类推
4、搜索选股:搜索关键词”医疗”
5、查看前10大持仓:按照持仓占比排列、确认是否都是医疗行业,例如成分“爱尔眼科” 持仓占比 9.18%
6、看净值走势
7、看业绩表现:阶段涨幅对比,近3年、今年来、近6个月、近3个月
8、对比市场平均水平、排名
9、对比特殊数据:近1年波动率(越小越好)、近1年夏普比例(越大越好)、近一年最大回撤(越小越好)
10、选择收益平稳度好一点的基金:对比4只股票的稳定性
十六、比较3只股票的夏普指数
import data.stock as st
import strategy.base as stb
import pandas as pd
import matplotlib.pyplot as plt
# 获取3只股票的数据:比亚迪、宁德时代、隆基
codes = ['002594.XSHE', '300750.XSHE', '601012.XSHG']
# 容器:存放夏普
sharpes = []
for code in codes:
data = st.get_single_stock_price(code, 'daily', '2022-10-01', '2023-01-01')
print(data.head())
# 计算每只股票的夏普比率
daily_sharpe, annual_sharpe = stb.calculate_sharpe(data)
sharpes.append([code, annual_sharpe]) # 存放 [[c1,s1],[c2,s2]..]
print(sharpes)
# 可视化3只股票并比较
sharpes = pd.DataFrame(sharpes, columns=['code', 'sharpe']).set_index('code')
print(sharpes)
# 绘制bar图
sharpes.plot.bar(title='Compare Annual Sharpe Ratio')
plt.xticks(rotation=30)
plt.show()
十七、如何创建、更新股票数据库
1、存储方式:
股票代码.csv
MySql、MangoDB等数据库
2、实现思路:
① 获取股票列表
② 依次存储股票数据
③ 每天以增量形式更新数据
如何追加数据:df.to_csv(mode = 'a')
重复获取了怎么办:df.drop_duplicates
缺少数据怎么办:startdate = 最后一个日期
十八、双均线策略:
1、均线 = 代表过去N日股价平均走势,5日均线
2、金叉买入死叉卖出
3、策略实现思路:
① 获取标的行情
② 计算技术指标: 移动平均现金:5日、10日
③ 生成交易信号:金叉则买入、死叉则卖出
④ 计算收益率:单次收益率、累计收益率
⑤ 寻找最优参数:均线周期、投资标的
⑥ 与市场基准比较:沪深300、上证、中证500
⑦ 策略评估:收益、夏普、波动率、回撤、胜率
4、均线代码:
#!/usr/bin/env python
# encoding: utf-8
'''
@author: DeltaF
@software: pycharm
@file: ma_strategy.py
@time: 2021/3/23 15:54
@desc:双均线策略
'''
import data.stock as st
import strategy.base as strat
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def ma_strategy(data, short_window=5, long_window=20):
"""
双均线策略
:param data: dataframe, 投资标的行情数据(必须包含收盘价)
:param short_window: 短期n日移动平均线,默认5
:param long_window: 长期n日移动平均线,默认20
:return:
"""
print("==========当前周期参数对:", short_window, long_window)
data = pd.DataFrame(data)
# 计算技术指标:ma短期、ma长期
data['short_ma'] = data['close'].rolling(window=short_window).mean()
data['long_ma'] = data['close'].rolling(window=long_window).mean()
# 生成信号:金叉买入、死叉卖出
data['buy_signal'] = np.where(data['short_ma'] > data['long_ma'], 1, 0)
data['sell_signal'] = np.where(data['short_ma'] < data['long_ma'], -1, 0)
# print(data[['close', 'short_ma', 'long_ma', 'buy_signal', 'sell_signal']])
# 过滤信号:st.compose_signal
data = strat.compose_signal(data)
# print(data[['close', 'short_ma', 'long_ma', 'signal']])
# 计算单次收益
data = strat.calculate_profit_pct(data)
# print(data.describe())
# 计算累计收益
data = strat.calculate_cum_prof(data)
# 删除多余的columns
data.drop(labels=['buy_signal', 'sell_signal'], axis=1)
# 数据预览
print(data[['close', 'short_ma', 'long_ma', 'signal', 'cum_profit']])
return data
if __name__ == '__main__':
# 股票列表
stocks = ['000001.XSHE', '000858.XSHE', '002594.XSHE']
# 存放累计收益率
cum_profits = pd.DataFrame()
# 循环获取数据
for code in stocks:
df = st.get_single_price(code, 'daily', '2022-05-01', '2023-01-01')
df = ma_strategy(df) # 调用双均线策略
cum_profits[code] = df['cum_profit'].reset_index(drop=True) # 存储累计收益率
# 折线图
df['cum_profit'].plot(label=code)
# 筛选有信号点
df = df[df['signal'] != 0]
# 预览数据
print("开仓次数:", int(len(df)))
print(df[['close', 'signal', 'cum_profit']])
# 预览
print(cum_profits)
# 可视化
# cum_profits.plot()
plt.legend()
plt.title('Comparison of Ma Strategy Profits')
plt.show()
十九、均线策略优化【55道令箭】:
1、均线策略优化1:“横有多长,竖有多高”连续12个月以上,每个月振幅在25%以内,判断股价处于横盘,叠加均线策略胜率在75.23%
2、均线策略优化2:“底部长下影”,股价在连续6个跌停板以上的下跌,出现长下影:下影线是实体的2倍以上,叠加均线策略胜率在82.51%
二十、验证策略的可靠性
1、评估指标:胜率、年华收益、最大回撤、夏普
2、假设检验:收益>0是否为大概率事件
3、H1:样本均值>理论均值,例如每次收益率的均值
4、统计量 = (样本均值 - 理论平均值) / (样本标准差/ 样本数量)
5、理解、模拟计算t值和p值:p值<显著性水平α(通常为0.05),则拒绝原假设
#!/usr/bin/env python
# encoding: utf-8
'''
@author: DeltaF
@software: pycharm
@file: statistical_test.py
@time: 2021/3/30 22:00
@desc:
'''
import data.stock as st
import strategy.ma_strategy as ma
import matplotlib.pyplot as plt
from scipy import stats
def ttest(data_return):
"""
对策略收益进行t检验
:param strat_return: dataframe,单次收益率
:return: float,t值和p值
"""
# 调用假设检验ttest函数:scipy
t, p = stats.ttest_1samp(data_return, 0, nan_policy='omit')
# 判断是否与理论均值有显著性差异:α=0.05
p_value = p / 2 # 获取单边p值
# 打印
print("t-value:", t)
print("p-value:", p_value)
print("是否可以拒绝[H0]收益均值=0:", p_value < 0.05)
return t, p_value
if __name__ == '__main__':
# 股票列表
stocks = ['000001.XSHE', '000858.XSHE', '002594.XSHE']
for code in stocks:
print(code)
df = st.get_single_price(code, 'daily', '2022-09-01', '2023-01-01')
df = ma.ma_strategy(df) # 调用双均线策略
# 策略的单次收益率
returns = df['profit_pct']
# print(returns)
# 绘制一下分布图用于观察
# plt.hist(returns, bins=30)
# plt.show()
# 对多个股票进行计算、测试
ttest(returns)
二十一、什么是动量策略:
1、定义:预先对股票收益和 交易量设定过滤准则,当股票收益或股票收益和交易量同时满足过滤准则就买入(做多)或者卖出(做空)股票的投资策略
2、交易原则:股票的历史交易率为主要的交易原则
3、提出理论:JT价格动量策略
4、设计思路:
正向策略:
涨的还会涨、跌的还会跌
买入长得最多的、卖出跌的最多的
利用市场对信息的反应不足
反向策略:
涨太多会跌、跌太多会涨
买入跌最多的、卖出涨最多的
市场对信息对信息反应过度
5、动量策略的实现步骤
① 确定交易对象:股票池、考虑流动性(沪深300、创业板)
② 选定业绩评价周期:过去1-12个月
③ 计算形成期收益率:过去N个月的收益率, 得出交易信号
④ 对收益率进行排序:最佳~赢家组合、最差~输家组合
⑤ 确定持仓/持仓周期:1个月、可自定义测算
⑥ 连续或间隔一段时期,不断重复②-⑤行为
⑦ 计算动量/反向策略各持有期的回报率
⑧ 计算t/p统计值,判断是否存在动量效应
⑨ 实现步骤:
确定投资标的;
计算动量因子;
计算投组收益率,并判断有效性;
6、确认股票池:
① 流动性:成交活跃、买入卖出顺畅
② 基本面:行业、营收、盈利增速、现金流、负债
③ 标的价格:1手起买起卖
股票池初始值:沪深300持有个股
④ 获取股票池
def get_data(index_symbol='000300.XSHG'):
# 获取股票列表代码:沪深300持有个股、创业板、上证
stocks = st.get_index_stocks(index_symbol,'2022-12-01')
# 获取股票数据
for code in stocks:
data = st.get_csv_price(code,start_date='2022-12-01', end_date='2022-12-31')
# 预览股票数据
print("==========", code)
print(data.tail())
7、动量因子:
明确计算公式:简单收益率
设置业绩评价周期:默认1个月
concat+列表循环拼接列数据
Resample函数转换日- 月周期
8、找交易信号、计算投资组合收益
#!/usr/bin/env python
# encoding: utf-8
'''
@author: DeltaF
@software: pycharm
@file: momentum_strategy.py
@time: 2021/4/14 23:35
@desc: 动量策略(正向)
'''
import data.stock as st
import pandas as pd
import numpy as np
import base
import matplotlib.pyplot as plt
def get_data(start_date, end_date, use_cols, index_symbol='000300.XSHG'):
"""
获取股票收盘价数据,并拼接为一个df
:param start_date: str
:param end_date: str
:param use_cols: list
:param index_symbol: str
:return data_concat: df,拼接后的数据表
"""
# 获取股票列表代码:沪深300持有个股、创业板、上证
stocks = st.get_index_list(index_symbol)
# 拼接收盘价数据
data_concat = pd.DataFrame()
# 获取股票数据
for code in stocks:
data = st.get_csv_price(code, start_date, end_date, use_cols)
# 拼接多个股票的收盘价:日期 股票A收盘价 股票B收盘价 ...
data.columns = [code]
data_concat = pd.concat([data_concat, data], axis=1)
# 预览股票数据
# print(data_concat.tail())
return data_concat
def momentum(data_concat, shift_n=1, top_n=4):
"""
:param data_concat: df
:param shift_n: int,表示业绩统计周期(单位:月)
:return:
"""
# 转换时间频率:日->月
data_concat.index = pd.to_datetime(data_concat.index)
data_month = data_concat.resample('M').last()
# 计算过去N个月的收益率 = 期末值/期初值 - 1 =(期末-期初)/ 期初
# optional:对数收益率 = log(期末值 / 期初值)
shift_return = data_month / data_month.shift(shift_n) - 1
print(shift_return.head())
# print(shift_return.shift(-1))
# 生成交易信号:收益率排前n的>赢家组合>买入1,排最后n个>输家>卖出-1
buy_signal = get_top_stocks(shift_return, top_n)
sell_signal = get_top_stocks(-1 * shift_return, top_n)
signal = buy_signal - sell_signal
print(signal.head())
# 计算投资组合收益率
returns = base.caculate_portfolio_return(shift_return, signal, top_n * 2)
print(returns.head())
# 评估策略效果:总收益率、年化收益率、最大回撤、夏普比
returns = base.evaluate_strategy(returns)
# 数据预览
# print(data_month.head())
return returns
def get_top_stocks(data, top_n):
"""
找到前n位的极值,并转换为信号返回
:param data: df
:param top_n: int, 表示要产生信号的个数
:return signals: df, 返回0-1信号数据表
"""
# 初始化信号容器
signals = pd.DataFrame(index=data.index, columns=data.columns)
# 对data的每一行进行遍历,找里面的最大值,并利用bool函数标注0或1信号
for index, row in data.iterrows():
signals.loc[index] = row.isin(row.nlargest(top_n)).astype(np.int64)
return signals
if __name__ == '__main__':
# 测试:获取沪深300个股数据
data = get_data('2023-01-01', '2023-04-04', ['date', 'close'])
# 测试:动量策略
returns = momentum(data)
# 存储结果
# returns.to_csv('/Users/ztnn/PycharmProjects/DeltaTrader/strategy/results/momentum.csv')
# 可视化每个月的收益率
# returns['cum_profit'].plot()
# plt.show()
9、投组收益率
def caculate_portfolio_return(data, signal, n):
"""
计算组合收益率
:param data: dataframe
:param signal: dataframe
:param n: int
:return returns: dataframe
"""
returns = data.copy()
# 投组收益率(等权重)= 收益率之和 / 股票个数
returns['profit_pct'] = (signal * returns.shift(-1)).T.sum() / n
returns = calculate_cum_prof(returns)
return returns.shift(1) # 匹配对应的交易月份
def calculate_cum_prof(data):
"""
计算累计收益率(个股收益率)
:param data: dataframe
:return:
"""
# 累计收益
data['cum_profit'] = pd.DataFrame(1 + data['profit_pct']).cumprod() - 1
return data
二十二、实盘交易处理买卖信号【EasyTrader】:
1、第二天买入
问题:① 错过最佳入场时机
② 成本变高了,次数多了,亏损概率提高
③ 滑点:实际交易与要求的价格不一致
2、用今天的分时价格代替日收盘价
二十三、数据回测框架【AlgoTrader】:
1、ZipLine:Quantopia、适用于美股、编程能力、开发环境
2、PyAlgoTrade:适用简单、股票、数字币、开源代码
3、BackTrader:内容全面、类定义复杂、可实盘交易
二十四、价差套利方法:
1、做法:例如十个交易所都有同一个资产、或者同一个币、或者同一个基金,然后他们价格不同,我在某个一个时间段都买入他们,哪一个价格低,我就卖出其他的买入低的,比如A交易所价格最低,把B、C、D交易所的都卖掉,买入A交易所,纯赚中间差价。如果哪天C交易所价格低,都卖掉,买C,我只需要监测是否有这种情况,有的话通过机器人或者交易系统去告知我,有的话,手工操作一下,不太适合很成熟的市场【例如A股市场】
二十五、适用PyAlgoTrade模拟交易与回测【双均线策略】:
#!/usr/bin/env python
# encoding: utf-8
'''
@author: DeltaF
@software: pycharm
@file: algotrade.py
@time: 2021/5/3 23:01
@desc: 使用pyalgotrade进行数据回测,详情:https://github.com/gbeced/pyalgotrade
'''
import pyalgotrade
import pyalgotrade_tushare
from pyalgotrade import strategy
from pyalgotrade_tushare import tools, barfeed
from pyalgotrade.technical import ma
from pyalgotrade import plotter
from pyalgotrade.stratanalyzer import returns
def safe_round(value, digits):
if value is not None:
value = round(value, digits)
return value
class MyStrategy(strategy.BacktestingStrategy):
def __init__(self, feed, instrument, smaPeriod1, smaPeriod2):
super(MyStrategy, self).__init__(feed, 10000) # 添加行情数据,以及买入金额
self.__position = None
self.__instrument = instrument
# We want a 15 period SMA over the closing prices.
self.__sma1 = ma.SMA(feed[instrument].getPriceDataSeries(), smaPeriod1)
self.__sma2 = ma.SMA(feed[instrument].getPriceDataSeries(), smaPeriod2)
def getSMA1(self):
return self.__sma1
def getSMA2(self):
return self.__sma2
def onEnterOk(self, position):
execInfo = position.getEntryOrder().getExecutionInfo()
# self.info("BUY at ¥%.2f" % (execInfo.getPrice()))
def onEnterCanceled(self, position):
self.__position = None
def onExitOk(self, position):
execInfo = position.getExitOrder().getExecutionInfo()
# self.info("SELL at ¥%.2f" % (execInfo.getPrice()))
self.__position = None
def onExitCanceled(self, position):
# If the exit was canceled, re-submit it.
self.__position.exitMarket()
def onBars(self, bars):
# Wait for enough bars to be available to calculate a SMA.
if self.__sma2[-1] is None:
return
bar = bars[self.__instrument]
# If a position was not opened, check if we should enter a long position.
if self.__position is None:
if self.__sma1[-1] > self.__sma2[-1]:
# Enter a buy market order for 100 shares. The order is good till canceled.
self.__position = self.enterLong(self.__instrument, 100, True)
# Check if we have to exit the position.
elif self.__sma1[-1] < self.__sma2[-1] and not self.__position.exitActive():
self.__position.exitMarket()
def run_strategy(smaPeriod1, smaPeriod2):
# Load the bar feed from the CSV file
instruments = ["000001"]
feeds = tools.build_feed(instruments, 2018, 2021, "histdata")
# print(feeds)
# Evaluate the strategy with the feed's bars.
myStrategy = MyStrategy(feeds, instruments[0], smaPeriod1, smaPeriod2)
# myStrategy.run()
# print(smaPeriod1, smaPeriod2, "Final portfolio value: ¥%.2f" % myStrategy.getBroker().getEquity())
# 可视化部分
# Attach a returns analyzers to the strategy.
returnsAnalyzer = returns.Returns()
myStrategy.attachAnalyzer(returnsAnalyzer)
# Attach the plotter to the strategy.
plt = plotter.StrategyPlotter(myStrategy)
# Include the SMA in the instrument's subplot to get it displayed along with the closing prices.
plt.getInstrumentSubplot(instruments[0]).addDataSeries("SMA1", myStrategy.getSMA1())
plt.getInstrumentSubplot(instruments[0]).addDataSeries("SMA2", myStrategy.getSMA2())
# Plot the simple returns on each bar.
plt.getOrCreateSubplot("returns").addDataSeries("Simple returns", returnsAnalyzer.getReturns())
# Run the strategy.
myStrategy.run()
myStrategy.info("Final portfolio value: $%.2f" % myStrategy.getResult())
# Plot the strategy.
plt.plot()
# 单均线
# for i in range(10, 30):
# 双均线
# ma1 = [5, 10, 15]
# ma2 = [15, 20, 30]
# for i in ma1:
# for j in ma2:
# if i < j:
# run_strategy(i, j)
run_strategy(15, 30)
二十六、不同交易所套利法则
1、不同交易卖同一股票,实时监测每一个交易所价格,每次找到最低价格例如交易所A第一时间买入,第二次找到更低的交易所B,则把A交易所股票卖出,B交易所股票买入,赚的就是差价
二十七、程序化交易的几种方式
1、对接券商:发送至交易所、授权信息、迥异和查询信息
2、交易柜台:宽睿、中泰、华鑫、华锐、恒生、面向机构
3、三方平台:万得、彭博、主流量化平台
4、个人投资者:网页模拟登录、基于exe接口
二十八、初始化EasyTrader开发环境
1、安装对象:
EasyTrader、客户端
使用pywinauto操作图形化界面
2、图形化界面:
软件页面、点选、拖拉拽
对应概念:字符、脚本、编辑模式
3、自动交易代码
#!/usr/bin/env python
# encoding: utf-8
'''
@author: DeltaF
@software: pycharm
@file: etrader.py
@time: 2021/5/19 22:17
@desc:
'''
# 可能的不兼容情况:no module name win32api
# 版本调整以解决不兼容:python 3.7.x - pywin32 221-223
import easytrader
# 设置客户端信息(同花顺)
user = easytrader.use('ths')
# 连接客户端(同花顺:登录且保存密码且自动登录)
user.connect(r'E:\同花顺\xiadan.exe') # 类似 r'C:\htzqzyb2\xiadan.exe'
# 设置客户端编辑文本形式:type_keys
user.enable_type_keys_for_editor()
# 调用常用函数
# 一类:查询类
# 查询持仓
balance = user.balance
print(balance)
# 查询持仓(仓位)
position = user.position
print(position)
# 二类:交易
# 买入
# buy_no = user.buy('000002', price=26.78, amount=100)
# print(buy_no)
# 卖出
sell_no = user.buy('000002', price='26.78', amount=100)
print(sell_no)
# 撤单:根据单号撤销,不稳定有效,待解决
# cancel = user.cancel_entrust('')
# print(cancel)
# 撤单:全部撤销
# cancel = user.cancel_all_entrusts()
# print(cancel)
# 查询当日成交
today_trades = user.today_trades
print(today_trades)
# 查询当日委托
today_entrusts = user.today_entrusts
print(today_entrusts)
二十九、多因子模型
1、因子:交易过程中的影响因素、技术/基本面指标
2、多因子:经过多个影响因子的筛选,形成的交易策略
3、价值投资选股器:根据盈利能力选股
① 确定股票池:
总市值、行业(排除房地产长周期等行业、偏好互联网、计算机、新能源)
② 筛选盈利能力(营收、净利润、ROE增幅):
经营活动净收益(亿元):近3年的平均增幅
净利润(亿元):近3年的平均增幅
ROE:近3年的平均增幅
③ 筛选估值水平(PE、PB)
PE、PB数值高说明很可能被高估,需要用增幅对比,结合行业一起去看
④ 筛选股价:
当前股价、增幅
三十、结合择时因子和动量因子结合就是选股模型
因子有效性
三十一、如何获取更多策略:
1、聚宽平台的十大策略:
北向资金、择时、趋势交易、选股
2、东方财富【重点分析】:资讯>A股研报>策略报告>搜索关键词:金融工程、因子、策略搜索
新闻舆情分析:消极关键词卖出、积极关键词多买入
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)