|  | @@ -5,6 +5,7 @@ import pandas as pd
 | 
	
		
			
				|  |  |  import pymysql
 | 
	
		
			
				|  |  |  import backtrader as bt
 | 
	
		
			
				|  |  |  import backtrader.indicators as btind
 | 
	
		
			
				|  |  | +import backtrader.analyzers as btanalyzers
 | 
	
		
			
				|  |  |  import datetime
 | 
	
		
			
				|  |  |  import math
 | 
	
		
			
				|  |  |  from datetime import datetime as dt
 | 
	
	
		
			
				|  | @@ -14,8 +15,10 @@ from numba import jit, cuda, njit
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  # import multiprocessing
 | 
	
		
			
				|  |  | -# import matplotlib
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +import matplotlib
 | 
	
		
			
				|  |  | +pd.set_option('display.max_columns', None) # 设置显示最大行
 | 
	
		
			
				|  |  | +# global result
 | 
	
		
			
				|  |  | +# result = pd.DataFrame(columns=['code', 'result', 'num', 'Volatility', 'rate'])
 | 
	
		
			
				|  |  |  class MyPandasData(PandasData):
 | 
	
		
			
				|  |  |      lines = ()
 | 
	
		
			
				|  |  |      params = ()
 | 
	
	
		
			
				|  | @@ -48,35 +51,7 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |      def log(self, txt, dt=None):
 | 
	
		
			
				|  |  |          ''' Logging function for this strategy'''
 | 
	
		
			
				|  |  |          dt = dt or self.datas[0].datetime.date(0)
 | 
	
		
			
				|  |  | -        # print('%s, %s' % (dt.isoformat(), txt))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def __init__(self):
 | 
	
		
			
				|  |  | -        print('__init__', dt.now())
 | 
	
		
			
				|  |  | -        print(f'{self.params.num}天波动率为{self.params.Volatility}%乖离率为{self.params.rate}', 'myPID is ', os.getpid())
 | 
	
		
			
				|  |  | -        # self.num = num
 | 
	
		
			
				|  |  | -        # self.Volatility = Volatility/100
 | 
	
		
			
				|  |  | -        # Keep a reference to the "close" line in the data[0] dataseries
 | 
	
		
			
				|  |  | -        self.dataclose = self.datas[0].close
 | 
	
		
			
				|  |  | -        self.dataopen = self.datas[0].open
 | 
	
		
			
				|  |  | -        self.high = self.datas[0].high
 | 
	
		
			
				|  |  | -        self.low = self.datas[0].low
 | 
	
		
			
				|  |  | -        self.volume = self.datas[0].volume
 | 
	
		
			
				|  |  | -        # self.change_pct = self.datas[0].change_pct
 | 
	
		
			
				|  |  | -        # self.net_amount_main = self.datas[0].net_amount_main
 | 
	
		
			
				|  |  | -        # self.net_pct_main = self.datas[0].net_pct_main
 | 
	
		
			
				|  |  | -        # self.net_amount_xl = self.datas[0].net_amount_xl
 | 
	
		
			
				|  |  | -        # self.net_pct_xl = self.datas[0].net_pct_xl
 | 
	
		
			
				|  |  | -        # self.net_amount_l = self.datas[0].net_amount_l
 | 
	
		
			
				|  |  | -        # self.net_pct_l = self.datas[0].net_pct_l
 | 
	
		
			
				|  |  | -        self.sma5 = btind.MovingAverageSimple(self.datas[0].close, period=5)
 | 
	
		
			
				|  |  | -        self.sma10 = btind.MovingAverageSimple(self.datas[0].close, period=10)
 | 
	
		
			
				|  |  | -        self.sma20 = btind.MovingAverageSimple(self.datas[0].close, period=20)
 | 
	
		
			
				|  |  | -        self.yx = self.dataclose[0] > self.dataopen[0]
 | 
	
		
			
				|  |  | -        self.lowest = btind.Lowest(self.params.num)
 | 
	
		
			
				|  |  | -        self.highest = btind.Highest(self.params.num)
 | 
	
		
			
				|  |  | -        self.vola = self.params.Volatility / 100
 | 
	
		
			
				|  |  | -        self.rate = self.params.rate / 100
 | 
	
		
			
				|  |  | +        print('%s, %s' % (dt.isoformat(), txt))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def notify_order(self, order):
 | 
	
		
			
				|  |  |          """
 | 
	
	
		
			
				|  | @@ -99,7 +74,7 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |          # 订单因为缺少资金之类的原因被拒绝执行
 | 
	
		
			
				|  |  |          elif order.status in [order.Canceled, order.Margin, order.Rejected]:
 | 
	
		
			
				|  |  |              pass
 | 
	
		
			
				|  |  | -            # self.log('Order Canceled/Margin/Rejected')
 | 
	
		
			
				|  |  | +            self.log('Order Canceled/Margin/Rejected')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          # 订单状态处理完成,设为空
 | 
	
		
			
				|  |  |          self.order = None
 | 
	
	
		
			
				|  | @@ -117,34 +92,83 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |          # 显示交易的毛利率和净利润
 | 
	
		
			
				|  |  |          # self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @njit
 | 
	
		
			
				|  |  | +    def __init__(self):
 | 
	
		
			
				|  |  | +        # print('__init__', dt.now())
 | 
	
		
			
				|  |  | +        # print(f'{self.params.num}天波动率为{self.params.Volatility}%乖离率为{self.params.rate}', 'myPID is ', os.getpid())
 | 
	
		
			
				|  |  | +        self.dataclose = self.datas[0].close
 | 
	
		
			
				|  |  | +        self.dataopen = self.datas[0].open
 | 
	
		
			
				|  |  | +        self.high = self.datas[0].high
 | 
	
		
			
				|  |  | +        self.low = self.datas[0].low
 | 
	
		
			
				|  |  | +        self.volume = self.datas[0].volume
 | 
	
		
			
				|  |  | +        # self.change_pct = self.datas[0].change_pct
 | 
	
		
			
				|  |  | +        # self.net_amount_main = self.datas[0].net_amount_main
 | 
	
		
			
				|  |  | +        # self.net_pct_main = self.datas[0].net_pct_main
 | 
	
		
			
				|  |  | +        # self.net_amount_xl = self.datas[0].net_amount_xl
 | 
	
		
			
				|  |  | +        # self.net_pct_xl = self.datas[0].net_pct_xl
 | 
	
		
			
				|  |  | +        # self.net_amount_l = self.datas[0].net_amount_l
 | 
	
		
			
				|  |  | +        # self.net_pct_l = self.datas[0].net_pct_l
 | 
	
		
			
				|  |  | +        self.sma5 = btind.MovingAverageSimple(self.datas[0].close, period=5)
 | 
	
		
			
				|  |  | +        self.sma10 = btind.MovingAverageSimple(self.datas[0].close, period=10)
 | 
	
		
			
				|  |  | +        self.sma20 = btind.MovingAverageSimple(self.datas[0].close, period=20)
 | 
	
		
			
				|  |  | +        self.yx = self.dataclose > self.dataopen
 | 
	
		
			
				|  |  | +        self.lowest = min(self.dataclose.get(ago=-1, size=self.params.num))
 | 
	
		
			
				|  |  | +        self.highest = max(self.high.get(ago=-1, size=self.params.num))
 | 
	
		
			
				|  |  | +        self.vola = self.params.Volatility / 100
 | 
	
		
			
				|  |  | +        self.rate = self.params.rate / 100
 | 
	
		
			
				|  |  | +        # print('初始化完成', dt.now())
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # @njit
 | 
	
		
			
				|  |  |      def next(self):
 | 
	
		
			
				|  |  | -        # print(self.num,self.Volatility)
 | 
	
		
			
				|  |  | -        # Simply log the closing price of the series from the reference
 | 
	
		
			
				|  |  | -        # self.sma20[-2] < self.sma20[-1] < self.sma20[0] and self.sma10[-2] < self.sma10[-1] < self.sma10[0]
 | 
	
		
			
				|  |  | -        # and (self.sma5[-1] < self.sma10[-1])
 | 
	
		
			
				|  |  | -        # and (self.net_pct_l[0] > 10) and (self.net_pct_xl[0] > 3)  \
 | 
	
		
			
				|  |  | -        # and (self.net_amount_main[-1] > 0) and (self.net_amount_main[0] > 0)
 | 
	
		
			
				|  |  | -        if len(self) > self.params.num:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            # print(f'{self.params.num}日天最低值:{lowest},波动率为{self.params.Volatility/100}')
 | 
	
		
			
				|  |  | -            if self.yx \
 | 
	
		
			
				|  |  | -                    and (((self.lowest[0] * (1 - self.vola)) < self.low[-2] < (self.lowest[0] * (1 + self.vola))) or (
 | 
	
		
			
				|  |  | -                    (self.lowest[0] * (1 - self.vola)) < self.low[-1] < (self.lowest[0] * (1 + self.vola)))) \
 | 
	
		
			
				|  |  | -                    and (self.dataclose[0] > self.sma5[0]) and self.sma5[0] > self.sma5[-1] \
 | 
	
		
			
				|  |  | -                    and (not self.position) and (self.sma5[0] > self.sma10[0]):
 | 
	
		
			
				|  |  | -                # self.log('BUY CREATE, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | -                self.order = self.buy()
 | 
	
		
			
				|  |  | -            elif self.dataclose < self.sma5[0] or self.sma5[0] < self.sma10[0] \
 | 
	
		
			
				|  |  | -                    or (self.dataclose[0] > (self.sma5[0] * (1 + self.rate))) or \
 | 
	
		
			
				|  |  | -                    (((self.highest[0] * (1 - self.vola)) < self.high[-2] < (self.highest[0] * (1 + self.vola))) or (
 | 
	
		
			
				|  |  | -                            (self.highest[0] * (1 - self.vola)) < self.high[-1] < (self.highest[0] * (1 + self.vola)))):
 | 
	
		
			
				|  |  | -                self.order = self.close()
 | 
	
		
			
				|  |  | -                # self.log('Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  | +                if self.yx and (self.dataclose[0] > self.dataclose[-1] > self.dataclose[-2])\
 | 
	
		
			
				|  |  | +                and self.sma5[0] > self.sma10[0] and self.sma5[-1] < self.sma10[-1]:
 | 
	
		
			
				|  |  | +            print('next', self.yx[0], (self.dataclose[0] > self.dataclose[-1] > self.dataclose[-2]),
 | 
	
		
			
				|  |  | +                  self.sma5[0] > self.sma10[0], self.sma5[-1] < self.sma10[-1])
 | 
	
		
			
				|  |  | +        :return:
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if self.yx and ((self.lowest * (1 - self.vola)) < self.low[-2] < (self.lowest * (1 + self.vola)))\
 | 
	
		
			
				|  |  | +                and self.dataclose[0] > self.dataclose[-1] > self.dataclose[-2] and self.dataclose[0] > self.sma5[0]:
 | 
	
		
			
				|  |  | +            # print(f'buy, {self.lowest},{self.vola},{self.low[-2]}, {self.rate}')
 | 
	
		
			
				|  |  | +            # self.log('BUY CREATE, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +            self.order = self.buy()
 | 
	
		
			
				|  |  | +        elif self.dataclose < self.sma5[0]:
 | 
	
		
			
				|  |  | +            self.order = self.close()
 | 
	
		
			
				|  |  | +            # self.log('close<ma5 Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +        elif self.sma5[0] < self.sma10[0]:
 | 
	
		
			
				|  |  | +            self.order = self.close()
 | 
	
		
			
				|  |  | +            # self.log('ma5<ma10 Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +        elif self.dataclose[0] > self.sma5[0]*(1+self.rate):
 | 
	
		
			
				|  |  | +            self.order = self.close()
 | 
	
		
			
				|  |  | +            # self.log('close>rate Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  | +                if self.yx \
 | 
	
		
			
				|  |  | +                and (((self.lowest[0] * (1 - self.vola)) < self.low[-2] < (self.lowest[0] * (1 + self.vola))) or (
 | 
	
		
			
				|  |  | +                (self.lowest[0] * (1 - self.vola)) < self.low[-1] < (self.lowest[0] * (1 + self.vola)))) \
 | 
	
		
			
				|  |  | +                and (self.dataclose[0] > self.sma5[0]) and self.sma5[0] > self.sma5[-1] \
 | 
	
		
			
				|  |  | +                and (not self.position) and (self.sma5[0] > self.sma10[0]):
 | 
	
		
			
				|  |  | +            # self.log('BUY CREATE, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +            self.order = self.buy()
 | 
	
		
			
				|  |  | +        elif self.dataclose < self.sma5[0] or self.sma5[0] < self.sma10[0] \
 | 
	
		
			
				|  |  | +                or (self.dataclose[0] > (self.sma5[0] * (1 + self.rate))) or \
 | 
	
		
			
				|  |  | +                (((self.highest[0] * (1 - self.vola)) < self.high[-2] < (self.highest[0] * (1 + self.vola))) or (
 | 
	
		
			
				|  |  | +                        (self.highest[0] * (1 - self.vola)) < self.high[-1] < (self.highest[0] * (1 + self.vola)))):
 | 
	
		
			
				|  |  | +            self.order = self.close()
 | 
	
		
			
				|  |  | +            # self.log('Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def stop(self):
 | 
	
		
			
				|  |  |          # pass
 | 
	
		
			
				|  |  | -        self.log(u'(MA趋势交易效果) Ending Value %.2f' % (self.broker.getvalue()))
 | 
	
		
			
				|  |  | +        global result
 | 
	
		
			
				|  |  | +        self.log(u'(MA趋势交易效果) Ending Value %.2f  num %d Vol %d rate %d' % (self.broker.getvalue(),
 | 
	
		
			
				|  |  | +                                                                                       self.params.num,
 | 
	
		
			
				|  |  | +                                                                                       self.params.Volatility,
 | 
	
		
			
				|  |  | +                                                                                       self.params.rate))
 | 
	
		
			
				|  |  | +        # self.log(f'time:{dt.now()}')
 | 
	
		
			
				|  |  | +        # temp = pd.DataFrame(columns=['code', 'result', 'num', 'Volatility', 'rate'],
 | 
	
		
			
				|  |  | +        #                     data=[self.getdatanames(), self.broker.getvalue(), self.params.num, self.params.rate])
 | 
	
		
			
				|  |  | +        # result = pd.concat([result,temp],axis=0)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def err_call_back(err):
 | 
	
	
		
			
				|  | @@ -160,24 +184,46 @@ def to_df(lt):
 | 
	
		
			
				|  |  |      print(df)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def backtrader(list_date, table_list, result, result_change, result_change_fall,  err_list):
 | 
	
		
			
				|  |  | +# 打印结果
 | 
	
		
			
				|  |  | +def get_my_analyzer(result):
 | 
	
		
			
				|  |  | +    analyzer = {}
 | 
	
		
			
				|  |  | +    # 返回参数
 | 
	
		
			
				|  |  | +    analyzer['num'] = result.params.num
 | 
	
		
			
				|  |  | +    analyzer['Volatility'] = result.params.Volatility
 | 
	
		
			
				|  |  | +    analyzer['rate'] = result.params.rate
 | 
	
		
			
				|  |  | +    # 提取年化收益
 | 
	
		
			
				|  |  | +    analyzer['年化收益率'] = result.analyzers._Returns.get_analysis()['rnorm']
 | 
	
		
			
				|  |  | +    analyzer['年化收益率(%)'] = result.analyzers._Returns.get_analysis()['rnorm100']
 | 
	
		
			
				|  |  | +    # 提取最大回撤(习惯用负的做大回撤,所以加了负号)
 | 
	
		
			
				|  |  | +    analyzer['最大回撤(%)'] = result.analyzers._DrawDown.get_analysis()['max']['drawdown'] * (-1)
 | 
	
		
			
				|  |  | +    # 提取夏普比率
 | 
	
		
			
				|  |  | +    analyzer['年化夏普比率'] = result.analyzers._SharpeRatio_A.get_analysis()['sharperatio']
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return analyzer
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def backtrader(table_list, result_change, result_change_fall,  err_list):
 | 
	
		
			
				|  |  |      sttime = dt.now()
 | 
	
		
			
				|  |  | -    engine = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/qmt_stocks?charset=utf8')
 | 
	
		
			
				|  |  | +    engine = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/qmt_stocks_front?charset=utf8')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    cerebro = bt.Cerebro()
 | 
	
		
			
				|  |  | -    # cerebro.addstrategy(TestStrategy, num=num, Volatility=Volatility, rate=rate)
 | 
	
		
			
				|  |  | -    cerebro.addsizer(bt.sizers.FixedSize, stake=10000)
 | 
	
		
			
				|  |  | +    cerebro = bt.Cerebro(stdstats=False)
 | 
	
		
			
				|  |  | +    # cerebro.addobserver(bt.observers.Broker)
 | 
	
		
			
				|  |  | +    # cerebro.addobserver(bt.observers.Trades)
 | 
	
		
			
				|  |  | +    # cerebro.addobserver(bt.observers.BuySell)
 | 
	
		
			
				|  |  | +    # cerebro.addobserver(bt.observers.DrawDown)
 | 
	
		
			
				|  |  | +    # cerebro.addobserver(bt.observers.TimeReturn)
 | 
	
		
			
				|  |  | +    # cerebro.addstrategy(TestStrategy)
 | 
	
		
			
				|  |  | +    cerebro.addsizer(bt.sizers.FixedSize, stake=1000)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      cerebro.broker.setcash(100000.0)
 | 
	
		
			
				|  |  |      cerebro.broker.setcommission(0.005)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for stock in table_list:
 | 
	
		
			
				|  |  | -        # print(stock)
 | 
	
		
			
				|  |  | +        print(stock)
 | 
	
		
			
				|  |  |          stk_df = pd.read_sql_table(stock, engine)
 | 
	
		
			
				|  |  |          stk_df.time = pd.to_datetime(stk_df.time)
 | 
	
		
			
				|  |  |          data = MyPandasData(dataname=stk_df,
 | 
	
		
			
				|  |  | -                            fromdate=datetime.datetime(2010, 1, 1),
 | 
	
		
			
				|  |  | -                            todate=datetime.datetime(2022, 12, 31),
 | 
	
		
			
				|  |  | +                            fromdate=datetime.datetime(2022, 1, 1),
 | 
	
		
			
				|  |  | +                            todate=datetime.datetime(2023, 2, 1),
 | 
	
		
			
				|  |  |                              datetime='time',
 | 
	
		
			
				|  |  |                              open='open',
 | 
	
		
			
				|  |  |                              close='close',
 | 
	
	
		
			
				|  | @@ -199,20 +245,66 @@ def backtrader(list_date, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          cerebro.adddata(data, name=stock)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    print('取值完成', dt.now())
 | 
	
		
			
				|  |  | -    cerebro.optstrategy(TestStrategy, num=range(60, 80, 20), Volatility=range(3, 7), rate=range(5, 12))
 | 
	
		
			
				|  |  | +    cerebro.optstrategy(TestStrategy, num=range(40, 130, 10), Volatility=range(5, 8), rate=range(5, 8))
 | 
	
		
			
				|  |  |      print('最优参定义', dt.now())
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    cerebro.addanalyzer(bt.analyzers.PyFolio)
 | 
	
		
			
				|  |  | +    # 添加分析指标
 | 
	
		
			
				|  |  | +    # 返回年初至年末的年度收益率
 | 
	
		
			
				|  |  | +    # cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='_AnnualReturn')
 | 
	
		
			
				|  |  | +    # 计算最大回撤相关指标
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(bt.analyzers.DrawDown, _name='_DrawDown')
 | 
	
		
			
				|  |  | +    # 计算年化收益:日度收益
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(bt.analyzers.Returns, _name='_Returns', tann=252)
 | 
	
		
			
				|  |  | +    # 计算年化夏普比率:日度收益
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='_SharpeRatio', timeframe=bt.TimeFrame.Days, annualize=True,
 | 
	
		
			
				|  |  | +                        riskfreerate=0)
 | 
	
		
			
				|  |  | +    # 计算夏普比率
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(bt.analyzers.SharpeRatio_A, _name='_SharpeRatio_A')
 | 
	
		
			
				|  |  | +    # 返回收益率时序
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='_TimeReturn')
 | 
	
		
			
				|  |  |      # 策略执行前的资金
 | 
	
		
			
				|  |  |      # print('启动资金: %.2f' % cerebro.broker.getvalue())
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    cerebro.addsizer(bt.sizers.PercentSizer, percents=10)
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(btanalyzers.SharpeRatio, _name="sharpe")
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(btanalyzers.DrawDown, _name="drawdown")
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(btanalyzers.Returns, _name="returns")
 | 
	
		
			
				|  |  | +    cerebro.addanalyzer(btanalyzers.TradeAnalyzer, _name='TradeAnalyzer')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      try:
 | 
	
		
			
				|  |  |          # 策略执行
 | 
	
		
			
				|  |  |          print('开始执行', dt.now())
 | 
	
		
			
				|  |  | -        cerebro.run(maxcpus=None)
 | 
	
		
			
				|  |  | +        results = cerebro.run(maxcpus=None)
 | 
	
		
			
				|  |  | +        print('回测结束', dt.now())
 | 
	
		
			
				|  |  |      except IndexError:
 | 
	
		
			
				|  |  |          err_list.append(stock)
 | 
	
		
			
				|  |  |      else:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        par_list = [[x[0].params.num,
 | 
	
		
			
				|  |  | +                     x[0].params.Volatility,
 | 
	
		
			
				|  |  | +                     x[0].params.rate,
 | 
	
		
			
				|  |  | +                     x[0].analyzers.returns.get_analysis()['rnorm100'],
 | 
	
		
			
				|  |  | +                     x[0].analyzers.drawdown.get_analysis()['max']['drawdown'],
 | 
	
		
			
				|  |  | +                     x[0].analyzers.sharpe.get_analysis()['sharperatio'],
 | 
	
		
			
				|  |  | +                     x[0].analyzers.TradeAnalyzer.get_analysis().won.total,
 | 
	
		
			
				|  |  | +                     ] for x in results]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        par_df = pd.DataFrame(par_list, columns=['num', 'Volatility', 'rate', 'return', 'drawdown', 'sharpe','TradeAnalyzer'])
 | 
	
		
			
				|  |  | +        print(par_df)
 | 
	
		
			
				|  |  | +        # par_df.to_csv('result.csv')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ret = []
 | 
	
		
			
				|  |  | +        for i in results:
 | 
	
		
			
				|  |  | +            ret.append(get_my_analyzer(i[0]))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        pd.DataFrame(ret)
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  |          if cerebro.broker.getvalue() > 100000.0:
 | 
	
		
			
				|  |  |              result_change.append((cerebro.broker.getvalue() / 10000 - 1))
 | 
	
		
			
				|  |  |              result.append(stock)
 | 
	
	
		
			
				|  | @@ -222,7 +314,7 @@ def backtrader(list_date, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  |              result_change_fall.append((1 - cerebro.broker.getvalue() / 10000))
 | 
	
		
			
				|  |  |              # print('aaaaaaaaaaa')
 | 
	
		
			
				|  |  |              # print(result_change_fall)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        '''
 | 
	
		
			
				|  |  |      # if len(result) * len(result_change) * len(result_change_fall) != 0:
 | 
	
		
			
				|  |  |      #     print(f'以{num}内最低值波动{Volatility}为支撑、乖离率为{rate}%,结果状态为:')
 | 
	
		
			
				|  |  |      #     print('正盈利的个股为:', len(result_change), '成功率为:', len(result) / len(table_list))
 | 
	
	
		
			
				|  | @@ -249,11 +341,6 @@ def backtrader(list_date, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  |  if __name__ == '__main__':
 | 
	
		
			
				|  |  |      starttime = dt.now()
 | 
	
		
			
				|  |  |      print(starttime)
 | 
	
		
			
				|  |  | -    # engine = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/hlfx?charset=utf8', poolclass=NullPool)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # stocks = pd.read_sql_query(
 | 
	
		
			
				|  |  | -    #                     'select value from MA5_1d', engine_hlfx)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      fre = '1d'
 | 
	
		
			
				|  |  |      db = pymysql.connect(host='localhost',
 | 
	
		
			
				|  |  |                           user='root',
 | 
	
	
		
			
				|  | @@ -264,43 +351,15 @@ if __name__ == '__main__':
 | 
	
		
			
				|  |  |      cursor.execute("show tables like '%%%s%%' " % fre)
 | 
	
		
			
				|  |  |      table_list = [tuple[0] for tuple in cursor.fetchall()]
 | 
	
		
			
				|  |  |      # print(table_list)
 | 
	
		
			
				|  |  | -    table_list = table_list[0:100]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    list_date = mp.Manager().list()
 | 
	
		
			
				|  |  | -    thread_list = []
 | 
	
		
			
				|  |  | -    pool = mp.Pool(processes=mp.cpu_count())
 | 
	
		
			
				|  |  | -    # for num in range(60, 100, 20):
 | 
	
		
			
				|  |  | -    #     for Volatility in range(3, 7, 1):
 | 
	
		
			
				|  |  | -    #         for rate in range(7, 9, 1):
 | 
	
		
			
				|  |  | -    step = math.ceil(len(table_list) / mp.cpu_count())
 | 
	
		
			
				|  |  | -    result = []
 | 
	
		
			
				|  |  | +    table_list = table_list[0:2]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      result_change = []
 | 
	
		
			
				|  |  |      result_change_fall = []
 | 
	
		
			
				|  |  |      err_list = []
 | 
	
		
			
				|  |  | -    # print(f'{num}天波动率为{Volatility}%乖离率为{rate}')
 | 
	
		
			
				|  |  | -    backtrader(list_date, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  | -                           err_list)
 | 
	
		
			
				|  |  | -                # for i in range(0, len(table_list), step):
 | 
	
		
			
				|  |  |      stattime = dt.now()
 | 
	
		
			
				|  |  | -    print(stattime)
 | 
	
		
			
				|  |  | -                # thd = threading.local()
 | 
	
		
			
				|  |  | -                # print(i)
 | 
	
		
			
				|  |  | -                # p = mp.Process(target=backtrader, args=(df, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  | -                #                                         num, Volatility, rate, err_list))
 | 
	
		
			
				|  |  | -                # thread_list.append(p)
 | 
	
		
			
				|  |  | -                # pool.apply_async(func=backtrader,
 | 
	
		
			
				|  |  | -                #                  args=(list_date, table_list, result, result_change, result_change_fall,
 | 
	
		
			
				|  |  | -                #                        num, Volatility, rate, err_list,), error_callback=err_call_back)
 | 
	
		
			
				|  |  | -                # p.start()
 | 
	
		
			
				|  |  | -                # p.join()
 | 
	
		
			
				|  |  | -                # print(thread_list)
 | 
	
		
			
				|  |  | -    # for thread in thread_list:
 | 
	
		
			
				|  |  | -    #     thread.start()
 | 
	
		
			
				|  |  | -    # for thread in thread_list:
 | 
	
		
			
				|  |  | -    #     thread.join()
 | 
	
		
			
				|  |  | -    pool.close()
 | 
	
		
			
				|  |  | -    pool.join()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    # print(f'{num}天波动率为{Volatility}%乖离率为{rate}')
 | 
	
		
			
				|  |  | +    backtrader(table_list,  result_change, result_change_fall, err_list)
 | 
	
		
			
				|  |  |      edtime = dt.now()
 | 
	
		
			
				|  |  |      print('总耗时:', edtime - starttime)
 | 
	
		
			
				|  |  |      # df.to_csv(r'C:\Users\Daniel\Documents\策略穷举2.csv', index=True)
 |