小果量化回测系统v1—-简单的回测多线程,提供源代码

这个周末话了2天把我的回测系统写完了,时间驱动回测,时间是核心,按真是的涨跌幅,价格进行交易,今天简单看一下后面给仔细的说明

链接 小果量化回测系统v1----简单的回测多线程,提供源代码 (qq.com)

回测长白山的源代码,简单的均线策略

from xgtrader_backtrader.backtrader import backtrader

from xgtrader_backtrader.user_def_data.user_def_data import user_def_datafrom xgtrader_backtrader.trader_tool import tdx_indicatorimport pandas as pdclass my_backtrader:    '''    多标的均线策略    外面可用采用提前计算买卖点的方式    也可用实时计算    '''    def __init__(self,start_date='20210105',end_date='20500101',data_type='D',                 starting_cash=10000,commission=0.001):        self.start_date=start_date        self.end_date=end_date        self.data_type=data_type        self.starting_cash=starting_cash        self.commission=commission        self.stock_list=['603099']        self.amount=100        self.trader=backtrader(start_date=self.start_date,end_date=self.end_date,                               data_type=self.data_type,starting_cash=self.start_date,commission=self.commission)        self.data=user_def_data(start_date=self.start_date,end_date=self.end_date,data_type=self.data_type)    def add_all_data(self):        '''        多线程加载数据        '''        self.data.get_thread_add_data(stock_list=self.stock_list)        self.hist=self.data.hist        return self.hist    def get_cacal_all_indicators(self):        '''        计算全部的指标        '''        hist=self.add_all_data()        trader_info=pd.DataFrame()        #拆分数据        for stock in self.stock_list:            df=hist[hist['stock']==stock]            df['mean_5']=df['close'].rolling(5).mean()            df['mean_10']=df['close'].rolling(10).mean()            df['buy']=df['mean_5']>df['mean_10']            df['sell']=df['mean_5']<df['mean_10']            trader_info=pd.concat([trader_info,df],ignore_index=True)        return trader_info    def run_backtrader(self):        '''        运行回测        '''        trader_list=self.trader.get_trader_date_list()        trader_info=self.get_cacal_all_indicators()        for date in trader_list:            df=trader_info[trader_info['date']==date]            stock_list=df['stock'].tolist()            for stock in stock_list:                df1=df[df['stock']==stock]                price=df1['close'].tolist()[-1]                price=float(price)                buy=df1['buy'].tolist()[-1]                sell=df1['sell'].tolist()[-1]                if buy==True:                    if self.trader.check_stock_is_av_buy(date=date,stock=stock,price=price,amount=self.amount):                        self.trader.buy(date=date,stock=stock,price=price,amount=self.amount)                    else:                        self.trader.settle(date=date,stock=stock,price=price)                elif sell==True:                    if self.trader.check_stock_is_av_sell(date=date,stock=stock,price=price,amount=self.amount):                        self.trader.sell(date=date,stock=stock,price=price,amount=self.amount)                    else:                        self.trader.settle(date=date,stock=stock,price=price)                else:                    self.trader.settle(date=date,stock=stock,price=price)if __name__=='__main__':    trader=my_backtrader()    trader.run_backtrader()    all_trader_data=trader.trader.get_position_all_trader_data()    all_hold_stock=trader.trader.get_total_position_pandas_data()    print(all_hold_stock)    all_trader_data.to_excel(r'全部的交易数据.xlsx')    account=trader.trader.get_total_portfolio_pandas_data()    print(account)    account.to_excel(r'全部的数据.xlsx')    #个股的交易数据    df=trader.trader.get_position_pandas_data_by_stock(stock='603099')    print(df)    df.to_excel(r'个股交易数据.xlsx')

框架非常的开放,内部封装了数据交易检查

回测的结果

图片

图片

图片

大概3秒完成,数据结果

图片

图片

外面看全部的交易数据

图片

图片

全部的账户数据

图片

图片

个股的交易数据

图片

图片

源代码全部上传可用加入下载,后面对接实盘,先实盘,回测一体

最后3 张

图片

回测框架源代码

图片

from xgtrader_backtrader.data.data import datafrom xgtrader_backtrader.portfolio.portfolio import portfoliofrom xgtrader_backtrader.position.position import positionfrom xgtrader_backtrader.indicators.indicators import indicatorsfrom xgtrader_backtrader.trader_tool.stock_data import stock_dataimport pandas as pdclass backtrader:    def __init__(self,start_date='20210105',end_date='20500101',data_type='D',starting_cash=10000,cash=10000,commission=0.001):        self.start_date=start_date        self.end_date=end_date        self.data_type=data_type        self.commission=commission        self.data=data(start_date=self.start_date,end_date=self.end_date)        self.position=position(start_date=self.start_date,end_date=self.end_date,starting_cash=starting_cash,                               data_type=self.data_type,commission=commission,cash=cash)        self.portfolio=portfolio(starting_cash=starting_cash,cash=cash)        self.stock_data=stock_data()    def check_is_creat_data(self,date='20230101',stock='60031',price=1,amount=100,trader_type='buy'):        '''        检查是否建立数据        '''        #建立账户        if  stock  in list(self.position.position.keys()):            #print('{} {}数据已经建立'.format(date,stock))            #print('{} {}数据账户建立'.format(date,stock))            return True        else:            #添加数据            print('{}数据没有建立开始建立'.format(stock))            self.data.get_add_data(stock=stock)            print('{}账户没有建立开始建立'.format(stock))            self.position.creat_position(stock=stock,start_date=date,price=price,amount=amount,trader_type='buy')            return False    def buy(self,date='20230101',stock='600031',price=1,amount=100,trader_type='buy'):        '''        买入        date交易时间        stock股票代码        price交易价格        amount数量        trader_type交易类型        '''        #检查数据是否加载        if self.check_is_creat_data(date=date,stock=stock,price=price,amount=amount)==True:            self.position.adjust_position_data(trader_type=trader_type,stock=stock,date=date,price=price,amount=amount)            return True, date ,stock,price,amount,trader_type        else:            print('数据没有建立建立数据{}'.format(stock,date))            return False, date ,stock,price,amount,trader_type    def sell(self,date='20230101',stock='600031',price=1,amount=100,trader_type='sell'):        '''        卖出        date交易时间        stock股票代码        price交易价格        amount数量        trader_type交易类型        '''        #检查数据是否加载        if self.check_is_creat_data(date=date,stock=stock,price=price,amount=amount)==True:            self.position.adjust_position_data(trader_type=trader_type,stock=stock,date=date,price=price,amount=amount)            return True, date ,stock,price,amount,trader_type        else:            print('数据没有建立建立数据{}'.format(stock,date))            return False, date ,stock,price,amount,trader_type    def settle(self,date='20230101',stock='600031',price=1,trader_type='settle',amount=100,):        '''        结算函数,持股结算        只有持有账户价值变化        date交易时间        stock股票代码        price交易价格        amount数量这个不需要为了兼容保留        trader_type交易类型        '''        #检查数据是否加载        if self.check_is_creat_data(date=date,stock=stock,price=price,amount=amount)==True:            self.position.adjust_position_data(trader_type=trader_type,stock=stock,date=date,price=price,amount=amount)            return True, date ,stock,price,amount,trader_type        else:            print('数据没有建立建立数据{}'.format(stock,date))            return False, date ,stock,price,amount,trader_type    def get_trader_date_list(self):        '''        获取交易日历        '''        trader_time=self.stock_data.get_trader_date_list(start_date=self.start_date,end_date=self.end_date)        return trader_time    def get_position_dict_data(self):        '''        获取持股数据字典类型的数据        '''        dict_data=self.position.position        return dict_data    def get_position_dict_data_by_stock(self,stock='600031'):        '''        获取持股数据字典类型的数据通过代码        '''        if stock in  list(self.position.position.keys()):            dict_data=self.position.position[stock]            return dict_data        else:            print('{}没有建立持股'.format(stock))            return {}    def get_position_pandas_data_by_stock(self,stock='600031'):        '''        获取持股数据字典类型的数据        '''        if stock in  list(self.position.position.keys()):            dict_data=self.position.position[stock]            df=pd.DataFrame(dict_data)            return df        else:            print('{}没有建立持股'.format(stock))            df=pd.DataFrame()            return df    def get_total_position_pandas_data(self):        '''        合并总持股数据        '''        df=self.position.get_total_position()        return df    def get_position_all_trader_data(self):        '''        获取全部交易数据        '''        df=self.position.get_total_position_trader()        return df    def get_total_portfolio_dict_data(self):        '''        获取总账户字典数据        '''        df=self.position.portfolio.total_portfolio        return df    def get_total_portfolio_pandas_data(self):        '''        获取总账户字典数据        '''        df=self.position.portfolio.get_portfolio_data_to_pandas()        return df    def get_portfolio_last_data(self):        '''        获取账户最新的数据        '''        df=self.get_total_portfolio_pandas_data()        data_dict={}        data_dict['date']=df['date'].tolist()[-1]        data_dict['stock_total_value']=df['stock_total_value'].tolist()[-1]        data_dict['available_cash']=df['available_cash'].tolist()[-1]        data_dict['ups_downs_value']=df['ups_downs_value'].tolist()[-1]        data_dict['reference_profit']=df['reference_profit'].tolist()[-1]        data_dict['host_cost']=df['host_cost'].tolist()[-1]        data_dict['cumsum_host_cost']=df['cumsum_host_cost'].tolist()[-1]        data_dict['total_value']=df['total_value'].tolist()[-1]        data_dict['return_ratio']=df['return_ratio'].tolist()[-1]        data_dict['cumsum_return_ratio']=df['cumsum_return_ratio'].tolist()[-1]        return data_dict    def get_position_last_data_by_stock(self,stock='600031'):        '''        获取个股最新持股数据        '''        if stock in  list(self.position.position.keys()):            data_dict={}            df=self.get_position_pandas_data_by_stock(stock=stock)            data_dict['stock']=df['stock'].tolist()[-1]            data_dict['price']=df['price'].tolist()[-1]            data_dict['date']=df['date'].tolist()[-1]            data_dict['host_cost']=df['host_cost'].tolist()[-1]            data_dict['cumsum_hold_cost']=df['cumsum_hold_cost'].tolist()[-1]            data_dict['amount']=df['amount'].tolist()[-1]            data_dict['trader_amount']=df['trader_amount'].tolist()[-1]            data_dict['trader_value']=df['trader_value'].tolist()[-1]            data_dict['value']=df['value'].tolist()[-1]            data_dict['price_limit']=df['price_limit'].tolist()[-1]            data_dict['ups_downs_value']=df['ups_downs_value'].tolist()[-1]            data_dict['return']=df['return'].tolist()[-1]            data_dict['cumsum_return']=df['cumsum_return'].tolist()[-1]            data_dict['trader_type']=df['trader_type'].tolist()[-1]            return data_dict        else:            print('{}没有建立持股'.format(stock))            return {}    def check_stock_is_av_buy(self,date='',stock='128036',price='156.700',amount=10):        '''        检查是否可用买入        '''        account=self.get_portfolio_last_data()        if stock not in  list(self.position.position.keys()):            print('时间{} {}没有持股直接买入'.format(date,stock))            return True        else:            buy_value=price*amount            av_cash=account['available_cash']            com=price*amount*self.commission            if av_cash>=buy_value+com:                print('时间{} {}允许买入 可用资金{} 买入价值{} 手续费{}'.format(date,stock,av_cash,buy_value,com))                return True            else:                print('时间{} {}不允许买入 可用资金{} 小于买入价值{} 加手续费{}'.format(date,stock,av_cash,buy_value,com))                return False    def check_stock_is_av_sell(self,date='',stock='128036',price='156.700',amount=10):        '''        检查是否可用卖出        '''        hold_stock=self.get_position_last_data_by_stock(stock=stock)        if stock not in  list(self.position.position.keys()):            print('时间{} {}没有持股不允许卖出'.format(date,stock))            return False        else:            sell_amount=amount            hold_amount=hold_stock['amount']            if hold_amount>=sell_amount:                print('时间{} {} 允许卖出 持有数量{} 卖出数量{}'.format(date,stock,hold_amount,sell_amount))                return True            else:                print('时间{} {} 不允许卖出 持有数量{} 小于卖出数量{}'.format(date,stock,hold_amount,sell_amount))                return False