1. 首先确定项目目的:
  2. 基于Tushare建立一个多组合的量化策略。
  3. 策略:1.趋势+择时
  4. 算法:选择SH300每月累积涨幅排名靠前的10只股票;然后择时,计算在金叉,死叉点进行买卖。

一、获取股票
df = pd.read_excel(’./沪深300.xlsx’,converters = {u’代码’:str}) #要加上,converters = {u’代码’:str} 不然 ‘000’就会被忽略掉啦
#然后遍历300只股票的收益率定义时间戳:这里选择20201220-2021220 然后预测2021320的收益排名; 注意这里要后复权,后复权做回测和计算利润率是用,前复权一般用来实盘比较好。
#这里利用tushare获取月收益
df_col = pd.DataFrame()
for code in df.loc[:,‘代码’]:
#给股票加上后缀sz sh
if code[0]‘6’ and code[1]‘0’:
code = code+’.SH’
#df = pro.monthly(ts_code=,start_date=‘20200401’, end_date=‘20200501’, fields=‘ts_code,pct_chg,trade_date’)
df = ts.pro_bar(ts_code=code, adj=‘hfq’, start_date=‘20200101’, end_date=‘20210101’) #还要判断此时是否还未上市,防止用到未来数据
if df is None :
continue
df = df[[‘ts_code’,‘open’,‘close’,‘pct_chg’]]
df[‘sum’]=df[‘pct_chg’].sum()
df_col = df_col.append(df[0:1])
df_col = df_col[[‘ts_code’,‘sum’]]
df_col .sort_values(by=‘sum’,inplace=True)
df_col.to_csv(‘12个月累积收益.csv’)

二、搭建策略(这里利用backtrader量化回测)

读取上述数据收益排名靠前的前十只股票和后十只股票(每日更新股票池)+择时

利用backtrader进行回测查看收益。
def get_data(code=‘code’,strattime=‘2021-01-01’,endtime=‘2022-01-01’):
df = ts.get_k_data(code=code,start=strattime,end=endtime)
df.index = pd.to_datetime(df.date)
df[‘OpenInterest’]=0
df = df[[‘open’,‘high’,‘low’,‘close’,‘volume’,‘OpenInterest’]]
return df

#第二步,数据有了,就开始构建自己的策略
class Mystrategy(bt.Strategy): #定义一个Mystratrgy类,然后来继承bt.Strategy
params = dict(period1=20, look_back_days=30,printlog=True)
#或者使用字典的形式。 params = dict(period1=, period2= period3=,)

def __init__(self):
    #定义参数 参数可以相互继承使用,这里只是需要申明变量
    self.order = None #此时没有订单处理.
    self.ma = dict()
    for data in self.datas:
        self.ma[data._name] = bt.indicators.SimpleMovingAverage(data.close,period=self.params.period1)  # 计算20日均线
  
def next(self):
    # 股票收益
    interest=[]
    if (self.order):#有交易订单的情况下待交易完。
        return
    for data in self.datas:
        if len(data)>self.params.look_back_days:
            p0=data.close[0]
            pn=data.close[-self.params.look_back_days]
            rate=(p0-pn)/pn
            interest.append([data._name,rate])
    stock_list=sorted(interest,key=lambda x:x[1],reverse=True)
    stock_head_10=[i[0] for i in interest[:9]]
    stock_back_10=[i[0] for i in interest[:-9]]
    # 得到当前的账户价值
    total_value = self.broker.getvalue()
    p_value = total_value * 0.9 / 10
    for data in self.datas:
        # 获取仓位
        pos = self.getposition(data).size
        # 建仓
        if not pos and data._name in stock_head_10 and \
                self.ma[data._name][0] > data.close[0]:
            size = int(p_value / 100 / data.close[0]) * 100
            self.buy(data=data, size=size)
        # 平仓
        if pos != 0 and data._name not in stock_head_10 or \
                self.ma[data._name][0] < data.close[0]:
            self.close(data=data)

买入月收益排名靠后的10只股票

‘’‘for data in self.datas:
# 获取仓位
pos = self.getposition(data).size
# 建仓
if not pos and data._name in stock_back_10 and
self.ma[data._name][0] > data.close[0]:
size = int(p_value / 100 / data.close[0]) * 100
self.buy(data=data, size=size)
# 平仓
if pos != 0 and data._name not in stock_back_10 or
self.ma[data._name][0] < data.close[0]:
self.close(data=data)’’’
def log(self, txt, dt=None, doprint=True):
if self.params.printlog or doprint:
dt = dt or self.datas[0].datetime.date(0)
print(f’{dt.isoformat()},{txt}’)

# 记录交易执行情况(可省略,默认不输出结果)
def notify_order(self, order):
    # 如果order为submitted/accepted,返回空
    if order.status in [order.Submitted, order.Accepted]:
        return
    # 如果order为buy/sell executed,报告价格结果
    if order.status in [order.Completed]:
        if order.isbuy():
            self.log(f'买入:\n价格:{order.executed.price:.2f},\
            成本:{order.executed.value:.2f},\
            手续费:{order.executed.comm:.2f}')

            self.buyprice = order.executed.price
            self.buycomm = order.executed.comm
        else:
            self.log(f'卖出:\n价格:{order.executed.price:.2f},\
            成本: {order.executed.value:.2f},\
            手续费{order.executed.comm:.2f}')

        self.bar_executed = len(self)

    # 如果指令取消/交易失败, 报告结果
    elif order.status in [order.Canceled, order.Margin, order.Rejected]:
        self.log('交易失败')

    self.order = None

# 记录交易收益情况(可省略,默认不输出结果)
def notify_trade(self, trade):
    if not trade.isclosed:
        return
    self.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}')

fromdate = dt(2021,1,1)
todate = dt(2022,2,1)

if name == ‘main’:
df=pd.read_csv(‘12个月累积收益.csv’)
# 策略设置
# 构建一个大脑
cerebro = bt.Cerebro()
# 给大脑输入数据
for code in (df[‘ts_code’]):
print(code)
code = ‘’.join(filter(str.isdigit,code))
stock_data = get_data(code,strattime=‘2021-01-01’,endtime=‘2022-02-01’)
data = bt.feeds.PandasData(dataname=stock_data, fromdate=fromdate, todate=todate)
cerebro.adddata(data)