一、量化交易:

        通过将与股票相关的信息数据化、策略化、并且通过历史数据验证它们的交易逻辑性

        我们从全部股票,选出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股研报>策略报告>搜索关键词:金融工程、因子、策略搜索

        新闻舆情分析:消极关键词卖出、积极关键词多买入

      

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐