从零实现一个支持深度强化学习的量化投资系统

研究过外汇自动交易,期货CTA,然后是股票的量化投资,当然本质上没有太大区别。

开源量化系统也用过几个,数据格式融合的问题,有些不方便,而且客观讲,实现一个简单的量化系统,其实非常简单。

这一次算是重构,希望它可以:

一、支持传统基于“规则”也就是技术分析为主的策略,包括投资组合、单支证券择时,多支证券轮动。

二、支持机器学习,深度强化学习等算法量化。

由于深度强化学习的环境是有openai确定规范的接口,所以,我们就按照强化学习的规则,实现一个A股基金的交易环境。

环境继承自gym.Env, env_data是从数据库加载数据并做好指标预计算备查,config就是相关的交易参数

class MarketEnv(gym.Env):    def __init__(self,env_data,config):        self.config = config        self.env_data = env_data

self.reset()

reset函数就是把环境初始化,下标零0,使用config里的benchmark做交易基准。数据我们是加载全量,calendar里去加载日期子集。这里有一个todo:可以判断universe里,日期最大的,以此为起点。

def reset(self):    self.i = 0    benchmark = self.config.benchmark    df = self.env_data.get_df_by_code(benchmark)    self.calendar = df.index[df.index>=self.config.start]    print('交易天数:{}'.format(len(self.calendar)))

    #初始有组合权重,未分配均为持仓占比为0,组合值为初始资金    self.last_weights = [0.0 for code in self.config.universe]    self.last_portfolio = self.config.init_cash

    self.weights_memory = []    self.portfolio_memory = []

给传统策略一个函数的接口(强化学习不使用这个接口)。它其实就是对calendar里每一个tick进行轮询,每个tick都会使用策略去取一个动作,动作如果是None则忽略,然后调用step去执行这个action。而强化学习是自己会调这个action。

def run(self,strategy):    self.strategy = strategy    done = False    while (not done):        action = strategy.get_action(self)        _, _, done, _ = self.step(action)    print('回测完成!')    self.analysis()

step函数会做三件事:

最后一件get_status是按强化学习的要求,返回obv,reward,done及info。如果i大于的calendar的长度,就是遍历结果。

def step(self,action=None):    #收盘后执行交易    # 根据收益率更新组合情况    #self.__update_portfolio()    #self.__do_action()    observation, reward, done, info = self.__get_status()

return observation,reward,done,info

先是根据universe里tick的收益率变化,更新组合净值。

def __update_portfolio(self):    df = self.env_data.get_data(self.calendar[self.i],self.config.universe)    rates = df['rate'].values

    #计算组合总的收益率 = 收益率加权求和    port_rate = sum(np.array(self.last_weights)*rates)    new_portfolio = self.last_portfolio * (1+port_rate)    new_weights = np.array(self.last_weights) * (1+rates) / (1+port_rate)

    #保存值    self.last_weights = new_weights    self.last_portfolio = new_portfolio

    self.weights_memory.append(new_weights)    self.portfolio_memory.append(new_portfolio)

然后执行Action,其实就是配置新的组合。这里没有计算交易手续费及滑点(todo)。

def __do_action(self,action):    if not action:        return    self.last_weights = action

第三步,返回状态。

def __get_status(self):    observation = self.env_data.get_data(self.calendar[self.i],self.config.universe)    #print(observation)    reward = None    info = {}    self.i += 1    done = False    if self.i > (len(self.calendar) - 1):        done = True    return observation, reward, done, info

这里reward是给强化学习使用的。后续再给出。

“买入并持有”的策略这样写:

class BuyHold(object):    def __init__(self,fix,rebalance='yearly'):        self.fix = fix        self.vars = None        self.rebalance = rebalance        #self.universe = universe    def get_action(self,env):        if env.i == 0:            return self.fix

        if self.rebalance:            if self.rebalance == 'yearly':                if env.i % 252 == 0:                    return self.fix        return None

就是第一步的时候,把权重配置为[0.2,0.8]即股债二八。

运行一下,结果长这样:

(公众号:七年实现财富自由(ailabx),用数字说基金,用基金做投资组合,践行财富自由之路)

(0)

相关推荐