|  | @@ -10,7 +10,6 @@ import math
 | 
	
		
			
				|  |  |  from datetime import datetime as dt
 | 
	
		
			
				|  |  |  import multiprocessing as mp
 | 
	
		
			
				|  |  |  from backtrader.feeds import PandasData
 | 
	
		
			
				|  |  | -from numba import jit, cuda, njit
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  # import multiprocessing
 | 
	
	
		
			
				|  | @@ -37,7 +36,6 @@ class MyPandasData(PandasData):
 | 
	
		
			
				|  |  |      '''
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |      params = (
 | 
	
		
			
				|  |  |          ("num", 3),
 | 
	
	
		
			
				|  | @@ -50,10 +48,7 @@ class TestStrategy(bt.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
 | 
	
	
		
			
				|  | @@ -72,11 +67,6 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |          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
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def notify_order(self, order):
 | 
	
		
			
				|  |  |          """
 | 
	
	
		
			
				|  | @@ -117,7 +107,6 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |          # 显示交易的毛利率和净利润
 | 
	
		
			
				|  |  |          # self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @njit
 | 
	
		
			
				|  |  |      def next(self):
 | 
	
		
			
				|  |  |          # print(self.num,self.Volatility)
 | 
	
		
			
				|  |  |          # Simply log the closing price of the series from the reference
 | 
	
	
		
			
				|  | @@ -126,19 +115,22 @@ class TestStrategy(bt.Strategy):
 | 
	
		
			
				|  |  |          # 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:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +            lowest = np.min(self.low.get(size=self.params.num))
 | 
	
		
			
				|  |  | +            highest = np.max(self.high.get(size=self.params.num))
 | 
	
		
			
				|  |  | +            vola = self.params.Volatility / 100
 | 
	
		
			
				|  |  | +            rate = self.params.rate / 100
 | 
	
		
			
				|  |  |              # 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)))) \
 | 
	
		
			
				|  |  | +            if (self.dataclose[0] > self.dataopen[0]) \
 | 
	
		
			
				|  |  | +                    and (((lowest * (1 - vola)) < self.low[-2] < (lowest * (1 + vola))) or (
 | 
	
		
			
				|  |  | +                    (lowest * (1 - vola)) < self.low[-1] < (lowest * (1 + 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)))):
 | 
	
		
			
				|  |  | +                    or (self.dataclose[0] > (self.sma5[0] * (1 + rate))) or \
 | 
	
		
			
				|  |  | +                    (((highest * (1 - vola)) < self.high[-2] < (highest * (1 + vola))) or (
 | 
	
		
			
				|  |  | +                            (highest * (1 - vola)) < self.high[-1] < (highest * (1 + vola)))):
 | 
	
		
			
				|  |  |                  self.order = self.close()
 | 
	
		
			
				|  |  |                  # self.log('Close, %.2f' % self.dataclose[0])
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -160,86 +152,79 @@ def to_df(lt):
 | 
	
		
			
				|  |  |      print(df)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def backtrader(list_date, table_list, result, result_change, result_change_fall,  err_list):
 | 
	
		
			
				|  |  | +def backtrader(list_date, table_list, result, result_change, result_change_fall, num, Volatility, rate, err_list):
 | 
	
		
			
				|  |  | +    print(f'{num}天波动率为{Volatility}%乖离率为{rate}', 'myPID is ', os.getpid())
 | 
	
		
			
				|  |  |      sttime = dt.now()
 | 
	
		
			
				|  |  |      engine = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/qmt_stocks?charset=utf8')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cerebro = bt.Cerebro()
 | 
	
		
			
				|  |  | -    # cerebro.addstrategy(TestStrategy, num=num, Volatility=Volatility, rate=rate)
 | 
	
		
			
				|  |  | -    cerebro.addsizer(bt.sizers.FixedSize, stake=10000)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cerebro.broker.setcash(100000.0)
 | 
	
		
			
				|  |  | -    cerebro.broker.setcommission(0.005)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      for stock in table_list:
 | 
	
		
			
				|  |  |          # 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),
 | 
	
		
			
				|  |  | -                            datetime='time',
 | 
	
		
			
				|  |  | -                            open='open',
 | 
	
		
			
				|  |  | -                            close='close',
 | 
	
		
			
				|  |  | -                            high='high',
 | 
	
		
			
				|  |  | -                            low='low',
 | 
	
		
			
				|  |  | -                            volume='volume',
 | 
	
		
			
				|  |  | -                            # change_pct='change_pct',
 | 
	
		
			
				|  |  | -                            # net_amount_main='net_amount_main',
 | 
	
		
			
				|  |  | -                            # net_pct_main='net_pct_main',
 | 
	
		
			
				|  |  | -                            # net_amount_xl='net_amount_xl',
 | 
	
		
			
				|  |  | -                            # net_pct_xl='net_pct_xl',
 | 
	
		
			
				|  |  | -                            # net_amount_l='net_amount_l',
 | 
	
		
			
				|  |  | -                            # net_pct_l='net_pct_l',
 | 
	
		
			
				|  |  | -                            # net_amount_m='net_amount_m',
 | 
	
		
			
				|  |  | -                            # net_pct_m='net_pct_m',
 | 
	
		
			
				|  |  | -                            # net_amount_s='net_amount_s',
 | 
	
		
			
				|  |  | -                            # net_pct_s='net_pct_s',
 | 
	
		
			
				|  |  | -                            )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        cerebro.adddata(data, name=stock)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    print('取值完成', dt.now())
 | 
	
		
			
				|  |  | -    cerebro.optstrategy(TestStrategy, num=range(60, 80, 20), Volatility=range(3, 7), rate=range(5, 12))
 | 
	
		
			
				|  |  | -    print('最优参定义', dt.now())
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cerebro.addanalyzer(bt.analyzers.PyFolio)
 | 
	
		
			
				|  |  | -    # 策略执行前的资金
 | 
	
		
			
				|  |  | -    # print('启动资金: %.2f' % cerebro.broker.getvalue())
 | 
	
		
			
				|  |  | -    try:
 | 
	
		
			
				|  |  | -        # 策略执行
 | 
	
		
			
				|  |  | -        print('开始执行', dt.now())
 | 
	
		
			
				|  |  | -        cerebro.run(maxcpus=None)
 | 
	
		
			
				|  |  | -    except IndexError:
 | 
	
		
			
				|  |  | -        err_list.append(stock)
 | 
	
		
			
				|  |  | +        if len(stk_df) > 60:
 | 
	
		
			
				|  |  | +            cerebro = bt.Cerebro()
 | 
	
		
			
				|  |  | +            cerebro.addstrategy(TestStrategy, num=num, Volatility=Volatility, rate=rate)
 | 
	
		
			
				|  |  | +            cerebro.addsizer(bt.sizers.FixedSize, stake=10000)
 | 
	
		
			
				|  |  | +            data = MyPandasData(dataname=stk_df,
 | 
	
		
			
				|  |  | +                                fromdate=datetime.datetime(2010, 1, 1),
 | 
	
		
			
				|  |  | +                                todate=datetime.datetime(2022, 10, 30),
 | 
	
		
			
				|  |  | +                                datetime='time',
 | 
	
		
			
				|  |  | +                                open='open',
 | 
	
		
			
				|  |  | +                                close='close',
 | 
	
		
			
				|  |  | +                                high='high',
 | 
	
		
			
				|  |  | +                                low='low',
 | 
	
		
			
				|  |  | +                                volume='volume',
 | 
	
		
			
				|  |  | +                                # change_pct='change_pct',
 | 
	
		
			
				|  |  | +                                # net_amount_main='net_amount_main',
 | 
	
		
			
				|  |  | +                                # net_pct_main='net_pct_main',
 | 
	
		
			
				|  |  | +                                # net_amount_xl='net_amount_xl',
 | 
	
		
			
				|  |  | +                                # net_pct_xl='net_pct_xl',
 | 
	
		
			
				|  |  | +                                # net_amount_l='net_amount_l',
 | 
	
		
			
				|  |  | +                                # net_pct_l='net_pct_l',
 | 
	
		
			
				|  |  | +                                # net_amount_m='net_amount_m',
 | 
	
		
			
				|  |  | +                                # net_pct_m='net_pct_m',
 | 
	
		
			
				|  |  | +                                # net_amount_s='net_amount_s',
 | 
	
		
			
				|  |  | +                                # net_pct_s='net_pct_s',
 | 
	
		
			
				|  |  | +                                )
 | 
	
		
			
				|  |  | +            # print('取值完成')
 | 
	
		
			
				|  |  | +            cerebro.adddata(data, name=stock)
 | 
	
		
			
				|  |  | +            cerebro.broker.setcash(100000.0)
 | 
	
		
			
				|  |  | +            cerebro.broker.setcommission(0.005)
 | 
	
		
			
				|  |  | +            cerebro.addanalyzer(bt.analyzers.PyFolio)
 | 
	
		
			
				|  |  | +            # 策略执行前的资金
 | 
	
		
			
				|  |  | +            # print('启动资金: %.2f' % cerebro.broker.getvalue())
 | 
	
		
			
				|  |  | +            try:
 | 
	
		
			
				|  |  | +                # 策略执行
 | 
	
		
			
				|  |  | +                cerebro.run()
 | 
	
		
			
				|  |  | +            except IndexError:
 | 
	
		
			
				|  |  | +                err_list.append(stock)
 | 
	
		
			
				|  |  | +            else:
 | 
	
		
			
				|  |  | +                if cerebro.broker.getvalue() > 100000.0:
 | 
	
		
			
				|  |  | +                    result_change.append((cerebro.broker.getvalue() / 10000 - 1))
 | 
	
		
			
				|  |  | +                    result.append(stock)
 | 
	
		
			
				|  |  | +                    # print('recode!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
 | 
	
		
			
				|  |  | +                    # print(result)
 | 
	
		
			
				|  |  | +                else:
 | 
	
		
			
				|  |  | +                    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))
 | 
	
		
			
				|  |  | +        print(
 | 
	
		
			
				|  |  | +            f'总盈利:{np.sum(result_change)} 平均盈利:{np.mean(result_change)},最大盈利:{np.max(result_change)}, 最小盈利:{np.min(result_change)}')
 | 
	
		
			
				|  |  | +        print(
 | 
	
		
			
				|  |  | +            f'总亏损:{np.sum(result_change_fall)},平均亏损:{np.mean(result_change_fall)},最大亏损:{np.min(result_change_fall)} 最小亏损:{np.max(result_change_fall)}')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        list_date.append([num, Volatility, rate, len(result), len(result) / len(table_list), np.nansum(result_change),
 | 
	
		
			
				|  |  | +                          np.nanmean(result_change), np.nanmax(result_change), np.min(result_change),
 | 
	
		
			
				|  |  | +                          np.nansum(result_change_fall), np.nanmean(result_change_fall),
 | 
	
		
			
				|  |  | +                          np.nanmin(result_change_fall), np.nanmax(result_change_fall)])
 | 
	
		
			
				|  |  | +        to_df(list_date)
 | 
	
		
			
				|  |  | +        endtime = dt.now()
 | 
	
		
			
				|  |  | +        print(f'{num}天波动率为{Volatility}%乖离率为{rate},myPID is {os.getpid()}.本轮耗时为{endtime - sttime}')
 | 
	
		
			
				|  |  |      else:
 | 
	
		
			
				|  |  | -        if cerebro.broker.getvalue() > 100000.0:
 | 
	
		
			
				|  |  | -            result_change.append((cerebro.broker.getvalue() / 10000 - 1))
 | 
	
		
			
				|  |  | -            result.append(stock)
 | 
	
		
			
				|  |  | -            # print('recode!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
 | 
	
		
			
				|  |  | -            # print(result)
 | 
	
		
			
				|  |  | -        else:
 | 
	
		
			
				|  |  | -            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))
 | 
	
		
			
				|  |  | -    #     print(
 | 
	
		
			
				|  |  | -    #         f'总盈利:{np.sum(result_change)} 平均盈利:{np.mean(result_change)},最大盈利:{np.max(result_change)}, 最小盈利:{np.min(result_change)}')
 | 
	
		
			
				|  |  | -    #     print(
 | 
	
		
			
				|  |  | -    #         f'总亏损:{np.sum(result_change_fall)},平均亏损:{np.mean(result_change_fall)},最大亏损:{np.min(result_change_fall)} 最小亏损:{np.max(result_change_fall)}')
 | 
	
		
			
				|  |  | -    #
 | 
	
		
			
				|  |  | -    #     list_date.append([num, Volatility, rate, len(result), len(result) / len(table_list), np.nansum(result_change),
 | 
	
		
			
				|  |  | -    #                       np.nanmean(result_change), np.nanmax(result_change), np.min(result_change),
 | 
	
		
			
				|  |  | -    #                       np.nansum(result_change_fall), np.nanmean(result_change_fall),
 | 
	
		
			
				|  |  | -    #                       np.nanmin(result_change_fall), np.nanmax(result_change_fall)])
 | 
	
		
			
				|  |  | -    #     to_df(list_date)
 | 
	
		
			
				|  |  | -    #     endtime = dt.now()
 | 
	
		
			
				|  |  | -    #     print(f'{num}天波动率为{Volatility}%乖离率为{rate},myPID is {os.getpid()}.本轮耗时为{endtime - sttime}')
 | 
	
		
			
				|  |  | -    # else:
 | 
	
		
			
				|  |  | -    #     print(result, result_change, result_change_fall, num, Volatility, rate, err_list)
 | 
	
		
			
				|  |  | +        print(result, result_change, result_change_fall, num, Volatility, rate, err_list)
 | 
	
		
			
				|  |  |      # cerebro.plot()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -269,28 +254,25 @@ if __name__ == '__main__':
 | 
	
		
			
				|  |  |      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 = []
 | 
	
		
			
				|  |  | -    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 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 = []
 | 
	
		
			
				|  |  | +                result_change = []
 | 
	
		
			
				|  |  | +                result_change_fall = []
 | 
	
		
			
				|  |  | +                err_list = []
 | 
	
		
			
				|  |  | +                print(f'{num}天波动率为{Volatility}%乖离率为{rate}')
 | 
	
		
			
				|  |  |                  # for i in range(0, len(table_list), step):
 | 
	
		
			
				|  |  | -    stattime = dt.now()
 | 
	
		
			
				|  |  | -    print(stattime)
 | 
	
		
			
				|  |  | +                stattime = dt.now()
 | 
	
		
			
				|  |  |                  # 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)
 | 
	
		
			
				|  |  | +                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)
 |