python量化交易第三章

一.股票交易快速入门

股票交易规则

  • 开户->炒股平台,券商(交易费)
  • 交易版面->K线,盘口,交易价格,数量(100股)
  • 交易费->佣金<3%,过户费1元每千股,印花税1%
  • A股特点—>±10%(主/中小板) ±20%(创业/科创板)

二.用shift函数计算涨跌幅

def calculate_change_pct(data):
    """
    涨跌幅=(当期收盘价-前期收盘价)/前期收盘价
    :param data:dataframe,带有收盘价
    :return:datafram,带有涨跌幅
    """
    data['close_pct']=(data['close']-data['close'].shift(1))/data['close'].shift(1)
    return data
import data.stock as st
#获取平安银行的行情数据(日K)
data=st.get_single_stock_Price('000001.XSHE','daily','2020-01-01','2020-02-01')
# print(data)

#计算涨跌幅,验证准确性
#data=st.calculate_change_pct(data)
# print(data)#多了一列close_pct
#获取周K
data=st.transfer_price_freq(data,'W')
print(data)

#计算涨跌幅,验证准确性
data=st.calculate_change_pct(data)
print(data)

三.模拟股票交易:买入,卖出

新建Strategy模块->创建周期选股策略->生成交易信号

import data.stock as st
import numpy as np
def week_period_strategy(code,time_freq,start_date,end_date):
    data=st.get_single_stock_Price(code,time_freq,start_date,end_date)
    #新建周期字段
    data['weekday']=data.index.weekday
    #周四买入
    data['buy_signal']=np.where((data['weekday']==3),1,0)
    #周一卖出
    data['sell_signal']=np.where((data['weekday']==0),-1,0)
    #整合信号
    data['buy_signal']=np.where((data['buy_signal']==1)&(data['buy_signal'].shift(1)==0),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
if __name__=='__main__':
    data=week_period_strategy('000001.XSHE','daily','2020-01-01','2020-03-01')
    print(data[['close','weekday','buy_signal','sell_signal','signal']])

四.模拟股票交易:计算持仓收益

总盈亏=(市价-成本价)× 股数
浮动盈亏比=(市价-成本价)/成本价
成本价=买入金额/持有股数
股数=累计买入股数

import datetime
import matplotlib.pyplot as plt
import data.stock as st
import numpy as np
def compose_signal(data):
    """
    整合信号
    :param data: 
    :return: 
    """
    data['buy_signal'] = np.where((data['buy_signal'] == 1) & (data['buy_signal'].shift(1) == 0), 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
def calculate_prof_pct(data):
    """
    计算单次收益率:开仓,平仓(开仓的全部股数)
    """
    data = data[data['signal'] != 0]  # 筛选
    data['profit_pct'] = ((data['close'] - data['close'].shift(1)) / data['close'].shift(1))
    data = data[data['signal'] == -1]
    return data
def week_period_strategy(code,time_freq,start_date,end_date):
    data=st.get_single_stock_Price(code,time_freq,start_date,end_date)
    #新建周期字段
    data['weekday']=data.index.weekday
    #周四买入
    data['buy_signal']=np.where((data['weekday']==3),1,0)
    #周一卖出
    data['sell_signal']=np.where((data['weekday']==0),-1,0)
    #整合信号
    data=compose_signal(data)
    data=calculate_prof_pct(data)
    return data

if __name__=='__main__':
    df=week_period_strategy('000001.XSHE','daily',None,datetime.date.today())
    print(df[['close','signal','profit_pct']])
    print(df.describe())
    #可视化
    df['profit_pct'].plot()
    plt.show()

持仓数据的计算->总盈亏,盈亏比,成本价,股数
计算单次收益率->最直接的策略收益评估指标
Matplotlib可视化->观察周期选股的收益表现

五.模拟股票交易:计算累计收益率

计算累计收益率->(1+当天收益率)的累计乘积-1

import datetime
import matplotlib.pyplot as plt
import pandas as pd

import data.stock as st
import numpy as np
def compose_signal(data):
    """
    整合信号
    :param data: 
    :return: 
    """
    data['buy_signal'] = np.where((data['buy_signal'] == 1) & (data['buy_signal'].shift(1) == 0), 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
def calculate_prof_pct(data):
    """
    计算单次收益率:开仓,平仓(开仓的全部股数)
    """
    data = data[data['signal'] != 0]  # 筛选
    data['profit_pct'] = ((data['close'] - data['close'].shift(1)) / data['close'].shift(1))
    data = data[data['signal'] == -1]
    return data
def calculate_cum_prof(data):
    """
    计算累计收益率
    :param data:dateframe
    :return:
    """
    data['cum_profit']=pd.DataFrame(1+data['profit_pct']).cumprod()-1
    return data
def week_period_strategy(code,time_freq,start_date,end_date):
    data=st.get_single_stock_Price(code,time_freq,start_date,end_date)
    #新建周期字段
    data['weekday']=data.index.weekday
    #周四买入
    data['buy_signal']=np.where((data['weekday']==3),1,0)
    #周一卖出
    data['sell_signal']=np.where((data['weekday']==0),-1,0)
    #整合信号
    data=compose_signal(data)#整合信号
    data=calculate_prof_pct(data)#计算收益
    data=calculate_cum_prof(data)#计算累计收益率
    return data

if __name__=='__main__':
    df=week_period_strategy('000001.XSHE','daily',None,datetime.date.today())
    print(df[['close','signal','profit_pct','cum_profit']])
    print(df.describe())
    #可视化
    df['cum_profit'].plot()
    plt.show()

六.计算风险指标:最大回撤

最大回撤->在选定周期内任一历史时点往后推,产品净值走到最低点时的收益率回撤幅度,是一个非常重要的风险指标

import datetime
import matplotlib.pyplot as plt
import pandas as pd

import data.stock as st
import numpy as np
def compose_signal(data):
    """
    整合信号
    :param data: 
    :return: 
    """
    data['buy_signal'] = np.where((data['buy_signal'] == 1) & (data['buy_signal'].shift(1) == 0), 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
def calculate_prof_pct(data):
    """
    计算单次收益率:开仓,平仓(开仓的全部股数)
    """
    data = data[data['signal'] != 0]  # 筛选
    data['profit_pct'] = ((data['close'] - data['close'].shift(1)) / data['close'].shift(1))
    data = data[data['signal'] == -1]
    return data
def calculate_cum_prof(data):
    """
    计算累计收益率
    :param data:dateframe
    :return:
    """
    data['cum_profit']=pd.DataFrame(1+data['profit_pct']).cumprod()-1
    return data
def caculate_max_drawdown(data):
    """
    计算最大回撤比
    :param data:
    :return:
    """
    #选取时间周期(时间窗口)
    window=252
    #选取时间周期中的最大净值
    data['roll_max']=data['close'].rolling(window=252,min_periods=1).max()
    #计算当天的回撤比=谷值/峰值-1
    data['daily_dd']=data['close']/data['roll_max']-1
    #选取时间周期内的最大回撤比,即最大回撤
    data['max_dd']=data['daily_dd'].rolling(window,min_periods=1).min()
    return data
def week_period_strategy(code,time_freq,start_date,end_date):
    data=st.get_single_stock_Price(code,time_freq,start_date,end_date)
    #新建周期字段
    data['weekday']=data.index.weekday
    #周四买入
    data['buy_signal']=np.where((data['weekday']==3),1,0)
    #周一卖出
    data['sell_signal']=np.where((data['weekday']==0),-1,0)
    #整合信号
    data=compose_signal(data)#整合信号
    data=calculate_prof_pct(data)#计算收益
    data=calculate_cum_prof(data)#计算累计收益率
    data=caculate_max_drawdown(data)#最大回撤
    return data

if __name__=='__main__':
    # df=week_period_strategy('000001.XSHE','daily',None,datetime.date.today())
    # print(df[['close','signal','profit_pct','cum_profit']])
    # print(df.describe())
    # #可视化
    # df['cum_profit'].plot()
    # plt.show()
    #查看平安银行最大回撤
    df=week_period_strategy('000001.XSHE','daily','2006-01-01','2021-01-01')
    df=caculate_max_drawdown(df)
    print(df[['close','roll_max','daily_dd','max_dd']])
    df[['daily_dd','max_dd']].plot()
    plt.show()

七.计算风险收益指标:夏普比率

7.1什么是夏普率
Sharpe Ratio:夏普指数,衡量的是一项投资在对其调整风险后,相对于无风险资产的收益表现。
在1966年,由威廉·F·夏普提出,美国金融经济学者,曾在1990年获得诺贝尔经济学奖.
夏普比率是投资者额外承受的每一单位的风险所获得的额外收益,夏普率越高越好

import datetime
import matplotlib.pyplot as plt
import pandas as pd

import data.stock as st
import numpy as np
def compose_signal(data):
    """
    整合信号
    :param data: 
    :return: 
    """
    data['buy_signal'] = np.where((data['buy_signal'] == 1) & (data['buy_signal'].shift(1) == 0), 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
def calculate_prof_pct(data):
    """
    计算单次收益率:开仓,平仓(开仓的全部股数)
    """
    data = data[data['signal'] != 0]  # 筛选
    data['profit_pct'] = ((data['close'] - data['close'].shift(1)) / data['close'].shift(1))
    data = data[data['signal'] == -1]
    return data
def calculate_cum_prof(data):
    """
    计算累计收益率
    :param data:dateframe
    :return:
    """
    data['cum_profit']=pd.DataFrame(1+data['profit_pct']).cumprod()-1
    return data
def caculate_max_drawdown(data):
    """
    计算最大回撤比
    :param data:
    :return:
    """
    #选取时间周期(时间窗口)
    window=252
    #选取时间周期中的最大净值
    data['roll_max']=data['close'].rolling(window=252,min_periods=1).max()
    #计算当天的回撤比=谷值/峰值-1
    data['daily_dd']=data['close']/data['roll_max']-1
    #选取时间周期内的最大回撤比,即最大回撤
    data['max_dd']=data['daily_dd'].rolling(window,min_periods=1).min()
    return data
def calculate_sharpe(data):
    """
    计算夏普比率,返回的是年化的夏普
    :param data:dateframe,stock
    :return:float
    """
    #公式:sharpe=(回报率的均值-无风险利率)/回报率的标准差
    #因子项
    daily_return=data['close'].pct_change()
    avg_return=daily_return.mean()
    sd_return=daily_return.std()
    #计算夏普:每日收益率*252=每年收益率
    sharpe=avg_return/sd_return
    sharpe_year=sharpe*np.sqrt(252)
    return sharpe,sharpe_year
def week_period_strategy(code,time_freq,start_date,end_date):
    data=st.get_single_stock_Price(code,time_freq,start_date,end_date)
    #新建周期字段
    data['weekday']=data.index.weekday
    #周四买入
    data['buy_signal']=np.where((data['weekday']==3),1,0)
    #周一卖出
    data['sell_signal']=np.where((data['weekday']==0),-1,0)
    #整合信号
    data=compose_signal(data)#整合信号
    data=calculate_prof_pct(data)#计算收益
    data=calculate_cum_prof(data)#计算累计收益率
    data=caculate_max_drawdown(data)#最大回撤
    return data

if __name__=='__main__':
    # df=week_period_strategy('000001.XSHE','daily',None,datetime.date.today())
    # print(df[['close','signal','profit_pct','cum_profit']])
    # print(df.describe())
    # #可视化
    # df['cum_profit'].plot()
    # plt.show()
    #查看平安银行最大回撤
    # df=st.get_single_stock_Price('000001.XSHE','daily','2006-01-01','2021-01-01')
    # df=caculate_max_drawdown(df)
    # print(df[['close','roll_max','daily_dd','max_dd']])
    # df[['daily_dd','max_dd']].plot()
    # plt.show()
    #获取计算夏普比率
    df = st.get_single_stock_Price('000001.XSHE', 'daily', '2006-01-01', '2021-01-01')
    sharpe=calculate_sharpe(df)
    print(sharpe)

八.比较3只股票的夏普指数

import pandas as pd

import data.stock as st
import strategy.base as stb
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','2018-10-01','2021-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()

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:datafram,单次收益率
    :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<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_stock_Price(code, 'daily', '2016-12-01', '2021-01-01')
        df = ma.ma_stratey(df)  # 调用双均线策略
         # 策略的单次收益率
        returns=df['profit_pct']
        # print(returns)

        #绘制一下分布图用于观察
        # plt.hist(returns,bins=30)
        # plt.show()
        #对多个股票进行计算,测试
        ttest(returns)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值