前两篇文章讲了数据的下载及更新,今天这篇文章讲回测系统的搭建。
回测系统
首先, 个人理解的回测系统就是输入每日可买入的股票(这些股票是经过模型筛选得到的),然后回测系统根据一些条件买入卖出等操作。
account类声明:
首先我们需要声明一个account类,记录账户的一些信息。具体需要记录的信息如下:(后期可能还会再加一些信息),信息初始化代码如下:
class Account:
def __init__(self, money_init, start_date='', end_date=''):
self.cash = money_init # 现金
self.stock_value = 0 # 股票价值
self.market_value = money_init # 总市值
self.stock_name = [] # 记录持仓股票名字
self.stock_id = [] # 记录持仓股票id
self.buy_date = [] # 记录持仓股票买入日期
self.stock_num = [] # 记录持股股票剩余持股数量
self.stock_price = [] # 记录股票的买入价格
self.start_date = start_date
self.end_date = end_date
self.stock_asset = [] # 持仓数量
self.buy_rate = 0.0003 # 买入费率
self.buy_min = 5 # 最小买入费率
self.sell_rate = 0.0003 # 卖出费率
self.sell_min = 5 # 最大买入费率
self.stamp_duty = 0.001 # 印花税
self.info = [] # 记录所有买入卖出记录
self.max_hold_period = 5 # 最大持股周期
self.hold_day = [] # 股票持股时间
self.cost = [] # 记录真实花费
# self.profit = [] # 记录每次卖出股票收益
self.stop_loss_rate = -0.03 # 止损比例
self.stop_profit_rate = 0.05 # 止盈比例
self.victory = 0 # 记录交易胜利次数
self.defeat = 0 # 记录失败次数
self.cash_all = [money_init] # 记录每天收盘后所持现金
self.stock_value_all = [0.0] # 记录每天收盘后所持股票的市值
self.market_value_all = [money_init] # 记录每天收盘后的总市值
self.max_market_value = money_init # 记录最大的市值情况,用来计算回撤
self.min_after_max_makret_value = money_init # 记录最大市值后的最小市值
self.max_retracement = 0 #记录最大回撤概率
回测需要一个股票的买入操作:
def buy_stock(self, buy_date, stock_name, stock_id, stock_price, buy_num):
"""
:param buy_date: 买入日期
:param stock_name: 买入股票的名字
:param stock_id: 买入股票的id
:param stcok_price: 买入股票的价格
:param buy_num: 买入股票的数量
:return:
"""
这里假设每支股票我们只买一次,不加仓,到止损点、止盈点或持股周期太长则全部卖出。所以加一个判断条件:
if stock_id not in self.stock_id:
如已在所买的股票中就不做买入操作,否则买入.
然后更新一些信息(包括尺寸股票id,买入日期,买入价格,该股持仓时间,现金).计算现金时,需要计算买入手续费,
self.stock_id.append(stock_id)
self.stock_name.append(stock_name)
self.buy_date.append(buy_date)
self.stock_price.append(stock_price)
self.hold_day.append(1)
# 更新市值、现金及股票价值
tmp_money = stock_price * buy_num
service_change = tmp_money * self.buy_rate
if service_change < self.buy_min:
service_change = self.buy_min
self.cash = self.cash - tmp_money - service_change
这个买入数量(buy_num)是我们预估的,可能会造成买入之后所剩现金无法付满手续,因此有以下代码
if self.cash < 0:
buy_num = buy_num - 100
tmp_money = stock_price * buy_num
service_change = tmp_money * self.buy_rate
if service_change < self.buy_min:
service_change = self.buy_min
self.cash = self.cash - tmp_money - service_change
self.stock_num.append(buy_num)
回测需要一个股票的卖出操作:
def sell_stock(self, sell_date, stock_name, stock_id, sell_price, sell_num, flag):
"""
:param sell_date: 卖出日期
:param stock_name: 卖出股票的名字
:param stock_id: 卖出股票的id