class Bot(): def __init__(self, order_size): print('started bot') self.__nn_threshold = 0.7 self.__nn = NN() self.__gene = [] self.__nn_input_data_generator = NNInputDataGenerator() self.__read_genes() self.num_genes = len(self.__gene) self.bot_accounts = [] for i in range(self.num_genes): self.bot_accounts.append(BotAccount(i)) self.__pred = {} self.__pred_log = {} self.__bot_started_time = datetime.now() self.__bot_elapsed_time = 0 self.__order_size = round(order_size / self.num_genes) self.__full_order_size = order_size th = threading.Thread(target=self.__bot_thread) th.start() def __initialize_combined_order_data(self): self.order_side_com = '' self.order_price_com = 0 self.order_qty_com = 0 def __read_genes(self): for f in glob.glob('./Model/*_best_weight.csv'): self.__gene.append(Gene(f, None, None)) print('Identified ', len(self.__gene), ' genes.') ''' 毎分MarketDataに最新のデータが準備されたことを確認して、各戦略のNN計算して必要なアクションを取る。 いずれかのBotAccountでorderがある時は約定データを取得してそれらのBotAccountに渡して約定確認・処理を行う。 ''' def __bot_thread(self): loop_num = 0 while SystemFlg.get_system_flg(): #毎分のデータ更新時の処理 if MarketData.get_ohlc_flg() == True: ohlc = MarketData.get_ohlc() index = MarketData.get_index() for i in range(self.num_genes ): #各戦略毎に新しい行動を計算して、実際に発注等する。結果をBotAccountに入力 order_data = self.bot_accounts[i].get_last_order_data() holding_data = self.bot_accounts[i].get_holding_data() performance_data = self.bot_accounts[ i].get_performance_data() nn_output = self.__nn_process(ohlc, index, i, order_data, holding_data, performance_data) actions = Strategy.ga_limit_market_strategy( nn_output, self.__order_size, self.__order_size, order_data, holding_data, i) print('#', i, ' - pred=', nn_output[0]) for j in range(len(actions.action)): if actions.action[j] == 'entry': res = Trade.order(actions.order_side[j], actions.order_price[j], actions.order_type[j], actions.order_size[j]) if res != None: self.bot_accounts[i].entry_order( res['info']['order_id'], res['info']['side'], res['info']['price'], res['info']['qty'], res['info']['order_type'], actions.order_message[j]) elif actions.action[ j] == 'cancel' and order_data['side'] != '': res = Trade.cancel_order(order_data['id']) if res != None: self.bot_accounts[i].cancel_order( order_data['id']) elif actions.action[j] == 'update amount': res = Trade.update_order_amount( actions.order_serial_num[j], actions.order_size[j]) if res != None: self.bot_accounts[i].update_order_amount( order_data['id'], actions.order_size[j]) elif actions.action[j] == 'update price': res = Trade.update_order_price( actions.order_serial_num[j], actions.order_price[j]) if res != None: self.bot_accounts[i].update_order_price( order_data['id'], actions.order_price[j]) else: print('Unknown strategy action-', actions.action[j]) self.bot_accounts[i].move_to_next(ohlc['datetime'], loop_num, ohlc, self.__order_size) loop_num += 1 #次のデータ更新まで未約定orderがある時に約定確認処理を継続する order_remaining_flg = True while MarketData.get_ohlc_flg() == False and order_remaining_flg: order_remaining_flg = False for i in range(self.num_genes): #未約定注文有無の確認 if len(self.bot_accounts[i].order_id) > 0: order_remaining_flg = True if order_remaining_flg == False: #未約定注文がなければ確認処理を停止 break else: exec_list = Trade.get_executions() if exec_list != None: #datetime unmatched errorで取得できないことがある。 for i in range(self.num_genes): if len(self.bot_accounts[i].order_id) > 0: self.bot_accounts[i].check_execution( exec_list) #未約定注文があるBotAccountに約定データを渡す time.sleep(3) time.sleep(1) print('Exited Bot thread loop !') LineNotification.send_message('Exited Bot thread loop !') def __nn_process(self, ohlc, index, account_id, order_data, holding_data, performance_data): nn_input = self.__nn_input_data_generator.generate_nn_input_data_limit( self.__gene[account_id].num_index, ohlc, index, order_data, holding_data, performance_data) nn_outputs = self.__nn.calc_nn(nn_input, self.__gene[account_id], 0) self.__pred[account_id] = self.__nn.getActivatedUnitLimitMarket2( nn_outputs, self.__nn_threshold ) #{0:'no', 1: 'buy', 2:'sell', 3:'cancel'}[nn_output] return self.__pred[account_id] def __calc_combined_orders(self): for i in range(self.num_genes): od = self.self.bot_accounts[i].get_last_order_data()
class Sim: def __init__(self, bool_display): print('started Sim.') SimAccount.initialize() self.loop_i = 0 self.max_amount = 1 self.nn = NN() self.nn_input_data_generator = NNInputDataGenerator() self.gene = Gene('./Model/best_weight.csv') self.pred = -1 self.pred_log = [] self.__bool_display = bool_display #True=display log th = threading.Thread(target=self.__sim_thread) th.start() def __sim_thread(self): while SystemFlg.get_system_flg(): if MarketData.ohlc_sim_flg == True: #毎分MarketDataでohlc / indexが更新されたことを確認 ohlc = MarketData.get_latest_ohlc( 0 ) #{'dt', 'open', 'high', 'low', 'close', 'divergence_scaled', 'vola_kyori_scaled} #SimAccountのpl / holding periodなどを更新 SimAccount.ohlc_update(self.loop_i, ohlc) #check invalid ac situation if SimAccount.getNumOrders() > 1: print('Sim: # of order is more than 1 !') #nnの計算を行い、strategyで必要なアクションを計算 self.__nn_process(ohlc['divergence_scaled'], ohlc['vola_kyori_scaled']) #SimAccountのorderを更新する。 actions = Strategy.sim_ga_limit_strategy( self.pred, 1, self.max_amount, ohlc) self.__sim_action_process(self.loop_i, actions, ohlc) #Log LogMaster.add_sim_holding_log(ohlc['dt'], SimAccount.get_holding_data()) LogMaster.add_sim_order_log(ohlc['dt'], SimAccount.get_order_data()) LogMaster.add_sim_performance_log( ohlc['dt'], SimAccount.get_performance_data()) LogMaster.add_sim_trade_log(ohlc['dt'], SimAccount.get_latest_trade_log()) #Display if self.__bool_display: print('') print( '**************************************************************************************************' ) print('i=', self.loop_i) del ohlc['divergence_scaled'] del ohlc['vola_kyori_scaled'] del ohlc['vol_ma_divergence_scaled'] print(ohlc) print('nn ouput=', { 0: 'no', 1: 'buy', 2: 'sell', 3: 'cancel' }[self.pred_log[-1]]) performance_log = SimAccount.get_performance_data() print( '----------------------------------------Performance Data--------------------------------------------' ) print(performance_log) print( '-------------------------------------------Holding Data---------------------------------------------' ) print(SimAccount.get_holding_data()) print( '--------------------------------------------Order Data----------------------------------------------' ) print(SimAccount.get_order_data()) print( '--------------------------------------------Trade Log-----------------------------------------------' ) print(SimAccount.get_latest_trade_log()) print( '**************************************************************************************************' ) #create pl chart plog = LogMaster.get_sim_performance_log() self.__generate_pl_chart(plog) #send message LineNotification.send_performance(performance_log) LineNotification.send_holding( SimAccount.get_holding_data()) if os.path.isfile('./Image/sim_pl.jpg'): LineNotification.send_image( open('./Image/sim_pl.jpg', 'rb')) self.loop_i += 1 time.sleep(1) def __nn_process(self, divergence_scaled, vola_kyori_scaled): nn_input = self.nn_input_data_generator.generate_nn_input_data_limit_sim( divergence_scaled, vola_kyori_scaled) nn_outputs = self.nn.calc_nn(nn_input, self.gene.num_units, self.gene.weight_gene1, self.gene.weight_gene2, self.gene.bias_gene1, self.gene.bias_gene2, 1) self.pred = self.nn.getActivatedUnit( nn_outputs) #{0:'no', 1: 'buy', 2:'sell', 3:'cancel'}[nn_output] self.pred_log.append(self.pred) #print('Sim: nn output=', self.pred, ':', {0:'no', 1: 'buy', 2:'sell', 3:'cancel'}[self.pred]) def __generate_pl_chart(self, plog): if len(plog) > 2: df = pd.concat([ pd.DataFrame(plog.values()), pd.DataFrame({'dt': plog.keys()}) ], axis=1) df = df.set_index('dt') fig, ax = plt.subplots() plt.plot(df.index, df['total_pl']) #plt.xticks(rotation=70) xfmt = mdates.DateFormatter("%d - %H:%M") ax.xaxis.set_major_formatter(xfmt) labels = ax.get_xticklabels() plt.setp(labels, rotation=45, fontsize=10) plt.show() plt.savefig('./Image/sim_pl.jpg') plt.close() def __sim_action_process(self, i, actions: ActionData, ohlc): for j in range(len(actions.action)): if actions.action[j] == 'entry': SimAccount.entry_order(i, actions.order_side[j], actions.order_price[j], actions.order_size[j], ohlc['dt'], actions.order_type[j], actions.order_message[j]) elif actions.action[j] == 'cancel': SimAccount.cancel_all_order(i) elif actions.action[j] == 'update amount': print('update amount is not programmed !') pass elif actions.action[j] == 'update price': SimAccount.update_order_price(i, actions.order_serial_num[j], actions.order_price[j]) else: print('Sim: Unknown strategy action !')