def handle_bar( counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Logistic regression with label = rising/falling signal. # Pattern for long signal: # When the predicted signal is rising, we long 1 BTC at the next bar; otherwise we short 1 BTC at the next bar. # Pattern for short signal: # When the predicted probability of rising is low (i.e., lower than 0.45), we short 1 BTC at the next bar. # No controlling of the position is conducted in this strategy. # Get position of last minute position_new = position_current # Generate OHLC data for every 30 minutes if (counter == 0): #memory.data_save = np.zeros((bar_length, 5))#, dtype=np.float64) memory.data_save = pd.DataFrame( columns=['close', 'high', 'low', 'open', 'volume']) if ((counter + 1) % bar_length == 0): memory.data_save.loc[bar_length - 1] = data[asset_index, ] bar = generate_bar(memory.data_save) # pandas dataframe bar_X = bar[['open', 'close']] prob_pred = model.predict_proba(bar_X)[:, 1] if (prob_pred > 0.55): position_new[asset_index] += 1 if (prob_pred < 0.45): position_new[asset_index] -= 1 else: memory.data_save.loc[(counter + 1) % bar_length - 1] = data[asset_index, ] ##### # End of strategy return position_new, memory
def load_training(self, filename, num=-1): data = {} for asset in range(4): data[asset] = [] data_format1_path = data_format1_dir + filename data_format2_path = data_format2_dir + filename.replace( 'format1', 'format2') format1 = h5py.File(data_format1_path, mode='r') format2 = h5py.File(data_format2_path, mode='r') #assets = list(format1.keys()) keys = list(format2.keys()) data_load = num if num != -1 else len(keys) for i in tqdm(range(data_load)): for asset in range(4): if len(data[asset]) == self.bar_length: data_cur_min = format2[keys[i]][:] data[asset].append(data_cur_min[asset, ]) segment = generate_bar(data[asset]) #print(segment) self.training_set[asset]['x'].append( segment[0:self.bar_length]) #tmp = [] ''' for k in range(len(segment[bar_length//2:bar_length])): if segment[i] < segment[bar_length//2+i]: tmp.append(2) ''' def norm(x): if x[0] > 0.05: return 2 elif x[0] >= -0.05: return 1 else: return 0 self.training_set[asset]['y'].append( norm(segment[self.bar_length])) data[asset].pop(0) else: data_cur_min = format2[keys[i]][:] data[asset].append(data_cur_min[asset, ]) self.data_size = len(self.training_set[asset]['y']) - self.pred_num
def handle_bar(counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Single alpha factor model for investment on BTC # The position of BTC is set by an alpha factor "(100*mean/CLOSE)*np.log(mean/1*std)" # When the operation on position will cause that the cash_balance is lower than 10000, this operation will be stop # Get position of last minute position_new = cp.deepcopy(position_current) # Generate OHLC data for every 30 minutes if (counter == 0): #memory.data_save = np.zeros((bar_length, 5))#, dtype=np.float64) memory.data_save = pd.DataFrame(columns = ['close', 'high', 'low', 'open', 'volume']) if ((counter + 1) % bar_length == 0): memory.data_save.loc[bar_length - 1] = data[asset_index,:5] bar = generate_bar(memory.data_save) # pandas dataframe #print(bar) aveopen=bar['ave_open'] aveclose=bar['ave_close'] avehigh=bar['ave_high'] avelow=bar['ave_low'] avemean=bar['ave_mean'] avestd=bar['ave_std'] avemed=bar['ave_med'] if (avelow[0]>(avemean[0]-1.5*avestd[0]) and avehigh[0] < (avemean[0]+1.5*avestd[0]) and (aveopen[0]+avelow[0])>1.9*avemean[0] and (aveclose[0]+avehigh[0])<2.1*avemean[0] and aveclose[0]<aveopen[0] ): print('small_drop') position_new[asset_index]=max(-(90*avemean[0]/aveclose[0])*np.log(avemean[0]/1*avestd[0]),-8) #if (LOW[0]<mean[0]-2*std[0] and # HIGH[0] > mean[0]+2*std[0] and # HIGH[0]-CLOSE[0]<std[0]): elif(avelow[0]>(avemean[0]-1.5*avestd[0]) and avehigh[0] < (avemean[0]+1.5*avestd[0]) and (aveopen[0]+avehigh[0])<2.1*avemean[0] and (aveclose[0]+avelow[0])>1.9*avemean[0] and aveclose[0]>aveopen[0] ): print('small_rise') position_new[asset_index]=min((90*avemean[0]/aveclose[0])*np.log(avemean[0]/1*avestd[0]),8) # Use an alpha factor "log(high/low)" to control the position of BTC elif(avelow[0]<(avemean[0]-2*avestd[0]) and avehigh[0] > (avemean[0]+2*avestd[0]) and (aveopen[0]+aveclose[0])<2*avemed[0] and #(aveopen[0]+avelow[0])<1.9*avemean[0] and #(aveclose[0]+avehigh[0])>2.1*avemean[0] and aveclose[0]<aveopen[0] ): print('large_drop') position_new[asset_index]=max(-(90*avemean[0]/aveclose[0])*np.log(avemean[0]/1*avestd[0]),-8) elif(avelow[0]<(avemean[0]-2*avestd[0]) and avehigh[0] > (avemean[0]+2*avestd[0]) and (aveopen[0]+aveclose[0])>2*avemed[0] and #(aveopen[0]+avehigh[0])>1.9*avemean[0] and #(aveclose[0]+avelow[0])<2.1*avemean[0] and aveclose[0]>aveopen[0] ): print('large_rise') position_new[asset_index]=min((90*avemean[0]/aveclose[0])*np.log(avemean[0]/1*avestd[0]),8) #position_new[asset_index]=-9 position_change = position_new - position_current mask = np.abs(position_change) > .25*data[:,4] position_change[mask] = (.25*data[:,4]*np.sign(position_change))[mask] position_new = position_current + position_change average_price = np.mean(data[:, :4], axis=1) transaction_cost = np.sum(np.abs(position_change)*average_price*transaction) crypto_balance = np.sum(np.abs(position_new*average_price)) cash_new=total_balance-crypto_balance-transaction_cost #print(position_new) #print(cash_new) if (cash_new<10000): position_new[asset_index]=np.sign(position_current[asset_index])*(abs(position_current[asset_index])/2) # When the operation on position will cause that the cash_balance is lower than 10000, this operation will be stop #print(position_new-position_new) else: memory.data_save.loc[(counter + 1) % bar_length - 1] = data[asset_index,:5]##### # End of strategy return position_new, memory
def handle_bar( counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Logistic regression with label = rising/falling signal. # Pattern for long signal: # for rising/falling prediction, long/short one unit of & according to the confidence to calculate the goal price, once it reachs sell the crypto. global deal_unit global piror global piror_weight global period global failed_count global decision_count global is_reverse global use_model # Get position of last minute position_new = position_current average_price_for_all_assets = np.mean(data[:, :4], axis=1) if counter == 0: memory.data_save = dict() memory.deal_save = list() # for each asset do the predict and make deal. for asset_index in range(4): # if counter > 60 * 24 * 5 and total_balance > 105000: # if total_balance > 105000: # position_new[asset_index] = 0 # continue average_price = average_price_for_all_assets[asset_index] fluctuate_volumn = fluctuate_volumn_for_each_crypto[asset_index] deal_unit = deal_unit_for_each_crypto[asset_index] # Generate OHLC data for every 30 minutes if (counter == 0): # memory.data_save = np.zeros((bar_length, 5))#, dtype=np.float64) memory.data_save[asset_index] = pd.DataFrame( columns=['close', 'high', 'low', 'open', 'volume']) # to support define outlier deals. memory.open_price = average_price memory.period_highest = dict() memory.period_lowest = dict() # check if any deal can sell in usual time. if len(memory.deal_save) > 0: for deal in memory.deal_save: if deal.asset_index != asset_index: continue if deal.is_dirty_deal and not deal.has_dropped: deal.drop_price = average_price deal.has_dropped = True if deal.has_selled or deal.has_dropped: continue if not deal.has_brought: # update record deal.deal_time = counter deal.price = average_price deal.goal_price += deal.price deal.has_brought = True deal.has_selled = False else: # process deal, see if could sell. if deal.deal_type == 'long' and average_price >= deal.goal_price: # sell long if not check_balance_warning( cash_balance, crypto_balance, total_balance, cash_balance_lower_limit, deal): position_new[asset_index] -= 1 * deal_unit deal.sell_time = counter deal.has_selled = True if deal.deal_type == 'short' and average_price <= deal.goal_price: # sell long if not check_balance_warning( cash_balance, crypto_balance, total_balance, cash_balance_lower_limit, deal): position_new[asset_index] += 1 * deal_unit deal.sell_time = counter deal.has_selled = True # predict in period if ((counter + 1) % period == 0): if check_balance_warning(cash_balance, crypto_balance, total_balance, cash_balance_lower_limit): continue memory.data_save[asset_index].loc[period - 1] = data[asset_index, ] # wether use a model to predict. if use_model: # use the model to predict bar = generate_bar( memory.data_save[asset_index]) # pandas dataframe bar_X = bar[['open', 'close']] prob_pred = model.predict_proba(bar_X)[:, 1][0] # prob_pred = -1 # random.random() is_up = prob_pred > 0.51 is_down = prob_pred < 0.49 else: # don't use model. judge trend based on the average price of last period & current price. hist_avg_price = get_history_avg_price( memory.data_save[asset_index].drop('volume', axis=1), period) curr_avg_price = get_current_avg_price(data[asset_index, ][:4]) prob_pred = 1 is_up = hist_avg_price < curr_avg_price is_down = hist_avg_price > curr_avg_price if decision_count > 150 and ( failed_count * 1.0) / decision_count > 0.7 and not is_reverse: is_reverse = True if is_reverse: is_up = not is_up is_down = not is_down make_deal = is_up or is_down confidence = prob_pred deal_type = 'none' if is_up: deal_type = 'long' position_new[asset_index] += 1 * deal_unit elif is_down: deal_type = 'short' position_new[asset_index] -= 1 * deal_unit if make_deal: decision_count += 1 # store deal deal_price = 0 # unknown yet, for now just a assumed price in this minute # TODO should also consider transaction fee. goal_price = deal_price + (1 if deal_type == 'long' else -1 ) * (piror_weight * piror + confidence) * fluctuate_volumn # deal = Deal_record(base_time='2018-08-01 00:00:00') deal = Deal_record(base_time='2018-10-07 00:00:00') deal.prob_pred = prob_pred deal.asset_index = asset_index deal.goal_price = goal_price deal.deal_type = deal_type deal.has_selled = False deal.has_brought = False memory.deal_save.append(deal) if len(memory.deal_save) > 0: for deal in memory.deal_save: if not deal.has_brought: continue if deal.has_selled: continue if deal.is_hold_till_end: continue if deal.is_dirty_deal: continue if (deal.deal_time) % period == 0: failed_count += 1 # deal.is_dirty_deal = True a_index = deal.asset_index # open_price_of_asset = memory.open_price[a_index] if piror > 0: # piror is the price will go up in final. # TODO deal with outliers. # if (deal.price < open_price_of_asset or (deal.price + pow((1 + piror), 2) * fluctuate_volumn) > open_price_of_index): if deal.deal_type == 'long': # hold till end and keep finding chance to sell deal.is_hold_till_end = True elif deal.deal_type == 'short': # sell directly to stop loss position_new[a_index] += 1 * deal_unit deal.is_dirty_deal = True pass if piror < 0: # piror is the price will go down in final. # TODO deal with outliers. # if (deal.price > open_price_of_asset or (deal.price + pow((1 + piror), 2) * fluctuate_volumn > open_price_of_index): if deal.deal_type == 'long': # sell directly to stop loss position_new[a_index] -= 1 * deal_unit deal.is_dirty_deal = True pass elif deal.deal_type == 'short': # hold till end and keep finding chance to sell deal.is_hold_till_end = True else: memory.data_save[asset_index].loc[(counter + 1) % period - 1] = data[asset_index, ] ##### # End of strategy return position_new, memory
AU = format1['AU.SHF'] AU_min = AU[:100] AU_15min = pd.concat([ AU[:600].open.resample('15min').first(), AU[:600].high.resample('15min').max(), AU[:600].low.resample('15min').min(), AU[:600].close.resample('15min').last(), AU[:600].volume.resample('15min').sum() ], axis=1).dropna() plot_candles(AU_min, volume_bars=True, title='AU 1-min Candle Chart') plot_candles(AU_15min, volume_bars=True, title='AU First 15-min Candle Chart') # Function test of bar combination, white soider pattern and black craw pattern from auxiliary import generate_bar, white_soider, black_craw # Bar combination test print('Combine first 15min data into one bar:') print(generate_bar(min_data[:15])) # White soider pattern test print('\nTest is 15-30min and 0-15min form white soider:') print( white_soider(generate_bar(min_data[15:30]), generate_bar(min_data[:15]))[1]) # Black craw pattern test print('\nTest is 15-30min and 0-15min form black craw:') print( black_craw(generate_bar(min_data[15:30]), generate_bar(min_data[:15]))[1])
def handle_bar( counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Logistic regression with label = rising/falling signal. # Pattern for long signal: # for rising/falling prediction, long/short one unit of & according to the confidence to calculate the goal price, once it reachs sell the crypto. # TODO: embeded utility functions def get_income_rate(position, cryp_balance, current_price, transaction): return_balance = position * current_price transaction_cost = position * current_price * transaction return_rate = (abs(cryp_balance - return_balance) - transaction_cost) / cryp_balance return return_rate def get_confidence(): pass # memory init if counter == 0: # data_save only saves data in the latest decision period (1 hour) memory.data_save = dict.fromkeys(ASSETS, pd.DataFrame(columns=ORIGIN_FEATURES)) memory.old_data = dict.fromkeys( ASSETS) # bakck up of data_save after one period memory.deal_save = dict.fromkeys(ASSETS, []) memory.turning_price = dict.fromkeys(ASSETS, 0) memory.invested_balance = dict.fromkeys( ASSETS, 0) # total money spent on the cryptos memory.last_prediction = 0 memory.is_satisfied = False # If True, stop to make deal memory.models_cof = [1 for i in range(4)] # confidence for each model memory.use_model = [True for i in range(4) ] # use model or not (this is for ensembled model) memory.success_count = dict.fromkeys(ASSETS, 0) memory.hourly_rf = pd.DataFrame(columns=[ 'rate_BCH', 'dVolume_BCH', 'rate_BTC', 'dVolume_BTC', 'rate_ETH', 'dVolume_ETH', 'rate_LTC', 'dVolume_LTC' ]) memory.hourly_var = pd.DataFrame(columns=['BCH', 'BTC', 'ETH', 'LTC']) # data preprocess & record update position_new = position_current average_prices = np.mean(data[:, :4], axis=1) # average price for all assets VAR = [0.5, 0.5, 0.5, 0.5] # Prediction for var model RF = [0.5, 0.5, 0.5, 0.5] # Prediction for Random Forest LR = [0.5, 0.5, 0.5, 0.5] # Prediction for Logistic regression if total_balance >= init_cash * (1 + EXPECT_RETURN_RATE): memory.is_satisfied = True else: memory.is_satisfied = False # for each asset do the predict and make deal. for asset_index in range(4): # when achieving target income, stop making deals # TODO: OR when is_satisfied is true & next prediction is opposite result, clean position for more income if memory.is_satisfied: position_new[asset_index] = 0 continue asset_name = ASSETS[asset_index] # fluctuate_volumn = FLUCTUATE_VOLUMNS[asset_index] deal_unit = DEAL_UNITS[asset_index] average_price = average_prices[asset_index] memory.data_save[asset_name].loc[counter] = data[asset_index, ] # predict in DECISION_PERIOD if ((counter + 1) % DECISION_PERIOD == 0): # Risk Ananlysis if check_balance_warning(cash_balance, crypto_balance, total_balance, CASH_BALANCE_LOWER_LIMIT): continue # Model Evaluation if len(memory.deal_save[asset_name]) > 0: last_deal = memory.deal_save[asset_name][-1] else: last_deal = None # if decision_count > 150 and (failed_count*1.0) / decision_count > 0.7 and not is_reverse: if last_deal and int( memory.data_save[asset_name].iloc[-DECISION_PERIOD]['open'] / memory.data_save[asset_name].iloc[-1]['close'] ) == last_deal.prediction: memory.success_count[asset_name] += 1 else: memory.models_cof[ asset_index] -= 0.01 # TODO better strategy needed if ((counter + 1) % (DECISION_PERIOD * 24 * 2) == 0): decision_count = int((counter + 1) / DECISION_PERIOD) if memory.success_count[asset_name] / decision_count <= 0.5: # memory.use_model[asset_index] = False print( f'Not trust {asset_name} model now, but still use it') # Do prediction: use model to predict or not if memory.use_model[asset_index]: ''' What should do here: load data for specified asset from memory.data_save[asset_name] transform data format according to diff models call model predict ensemble result give final prediction: 1: increasing, 0: decreasing, 2: hold the line (it's no matter without 2) ''' bar_x = generate_bar(memory.data_save[asset_name], barlength=BAR_LENGTH) x = [] for j in range(4): start = int(BAR_LENGTH * j / 4) end = int(BAR_LENGTH * (j + 1) / 4) x.append(bar_x.values[start:end, 0].mean()) y1 = model_list[asset_index][0].predict(x) y2 = model_list[asset_index][1].predict(x) y3 = model_list[asset_index][2].predict(x) predict_price = (y1 + y2 + y3) / 3 if predict_price > memory.last_prediction: prediction = 1 elif predict_price < memory.last_prediction: prediction = 0 else: prediction = -1 memory.last_prediction = predict_price else: # NOT sure is it a better way to replacce model prediction # # don't use model. judge trend based on the average price of last DECISION_PERIOD & current price. # hist_avg_price = get_history_avg_price(memory.data_save[asset_name].drop('volume', axis=1), DECISION_PERIOD) # curr_avg_price = get_current_avg_price(data[asset_index,][:4]) # # prob_pred = 1 # prediction = 1 if hist_avg_price < curr_avg_price else 0 position_new[asset_index] = 0 continue # TODO: consider transaction fee and calculate income rate to refine deal unit if prediction == LONG: deal_type = 'long' if position_new[asset_index] > 0: position_new[asset_index] += int( deal_unit * memory.models_cof[asset_index]) # Assume that new open = last close or avg memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price elif position_new[asset_index] == 0: position_new[asset_index] += int( deal_unit * memory.models_cof[asset_index]) memory.turning_price[asset_name] = average_price memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price else: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 elif prediction == SHORT: deal_type = 'short' if position_new[asset_index] <= 0: position_new[asset_index] -= int( deal_unit * memory.models_cof[asset_index]) memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price elif position_new[asset_index] == 0: position_new[asset_index] -= int( deal_unit * memory.models_cof[asset_index]) memory.turning_price[asset_name] = average_price memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price else: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 elif prediction == HOLD: # HOLD deal_type = 'none' # record deal deal_price = memory.data_save[asset_name].iloc[-1][ 'close'] # unknown yet, for now just a assumed close price in this minute deal = Deal_record(amount=int(deal_unit * memory.models_cof[asset_index])) deal.prob_pred = memory.models_cof[asset_index] deal.asset_index = asset_index # deal.goal_price = deal_price + (1 if deal_type == 'long' else -1) * (PRIOR_WEIGHT * PRIOR + confidence) * fluctuate_volumn deal.deal_type = deal_type deal.prediction = prediction memory.deal_save[asset_name].append(deal) elif (counter != 0): # not decision period & not the first minute # if current currency price can give double expect return, clean position return_rate = get_income_rate(position_new[asset_index], memory.invested_balance[asset_name], average_price, transaction) if return_rate >= EXPECT_RETURN_RATE: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 # End of strategy return position_new, memory
def handle_bar(timer, data, info, init_cash, transaction, detail_last_min, memory): ''' Params: timer = int, counter of current time data = pandas.dataframe, data for current minute bar info - pandas.dataframe, information matrix init_cash,transaction - double, constans detail_last_min - list, contains cash balance, margin balance, total balance and position of last minute memory - class, current memory of your strategy ''' # Get position of last minute position_new = detail_last_min[0] # Generate OHLC data for every 15 minutes if (timer == 0): memory.data_list = list() memory.bar_prev = np.array([None]) memory.ws_check_table = np.empty((0, 2)) memory.bc_check_table = np.empty((0, 2)) memory.long_stop_loss = np.inf memory.long_profit_target = np.inf memory.short_stop_loss = np.inf memory.short_profit_target = np.inf if (timer % bar_length == 0 and timer != 0): memory.data_list.append(data) bar = generate_bar(memory.data_list) memory.data_list = list( ) # Clear memory.data_list after bar combination if memory.bar_prev.any() != None: ws_check = white_soider(bar, memory.bar_prev, asset_index) memory.ws_check_table = np.append(memory.ws_check_table, [ws_check], axis=0) bc_check = black_craw(bar, memory.bar_prev, asset_index) memory.bc_check_table = np.append(memory.bc_check_table, [bc_check], axis=0) bar_num = len(memory.ws_check_table) if bar_num > 3: ''' long signal When there is a three white soider signal, long 10 lots of asset at next minute unless the current cash balance is less than 3,000,000 ''' if np.sum(memory.ws_check_table[bar_num - 3:bar_num, 1]) == 3: if detail_last_min[1] > my_cash_balance_lower_limit: position_new[asset_index] += 10. memory.long_stop_loss = memory.ws_check_table[bar_num - 3, 0] memory.long_profit_target = memory.ws_check_table[ bar_num - 1, 0] * (1 + .05) ''' short signal When there is a three black craw signal, short 10 lots of asset at next minute unless the current cash balance is less than 3,000,000 ''' if np.sum(memory.bc_check_table[bar_num - 3:bar_num, 1]) == 2: if detail_last_min[1] > my_cash_balance_lower_limit: position_new[asset_index] -= 10. memory.short_stop_loss = memory.bc_check_table[bar_num - 3, 0] memory.short_profit_target = memory.bc_check_table[ bar_num - 1, 0] * (1 + .05) memory.bar_prev = bar # save minute data to data_list else: memory.data_list.append(data) # Close signal # When reach stop loss/target profit points, clear all long/short positions average_price = np.mean(data[asset_index, :4]) if (position_new[asset_index] > 0): if average_price > memory.long_profit_target or average_price < memory.long_stop_loss: position_new[asset_index] = 0. else: if average_price > memory.short_stop_loss or average_price < memory.short_profit_target: position_new[asset_index] = 0. # End of strategy return position_new, memory
def handle_bar( counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Logistic regression with label = rising/falling signal. # Pattern for long signal: # for rising/falling prediction, long/short one unit of & according to the confidence to calculate the goal price, once it reachs sell the crypto. # TODO: embeded utility functions def get_income_rate(position, cryp_balance, current_price, transaction): return_balance = position * current_price transaction_cost = position * current_price * transaction if cryp_balance == 0: return_rate = 0 elif cryp_balance > 0: return_rate = ((return_balance - cryp_balance) - transaction_cost) / cryp_balance else: return_rate = ((abs(cryp_balance) - return_balance) - transaction_cost) / cryp_balance return return_rate def get_confidence(): pass # memory init if counter == 0: # data_save only saves data in the latest decision period (1 hour) memory.data_save_name = dict.fromkeys( ASSETS, pd.DataFrame(columns=ORIGIN_FEATURES)) memory.deal_save = dict.fromkeys(ASSETS, []) memory.turning_price = dict.fromkeys(ASSETS, 0) memory.invested_balance = dict.fromkeys( ASSETS, 0) # total money spent on the cryptos memory.last_prediction = dict.fromkeys(['xgb', 'lstm'], 0) memory.is_satisfied = False # If True, stop to make deal memory.models_cof = [1 for i in range(4)] # confidence for each model memory.use_model = [True for i in range(4) ] # use model or not (this is for ensembled model) memory.success_count = dict.fromkeys(ASSETS, 0) memory.data_save_index = [] memory.data_cryp = [] for i in range(4): #memory.data_save = np.zeros((DECISION_PERIOD, 5))#, dtype=np.float64) memory.data_save_index.append( pd.DataFrame( columns=['close', 'high', 'low', 'open', 'volume'])) memory.data_cryp.append( pd.DataFrame( columns=['close', 'high', 'low', 'open', 'volume'])) memory.hourly_rf = pd.DataFrame(columns=[ 'rate_BCH', 'dVolume_BCH', 'rate_BTC', 'dVolume_BTC', 'rate_ETH', 'dVolume_ETH', 'rate_LTC', 'dVolume_LTC' ]) memory.hourly_var = pd.DataFrame(columns=['BCH', 'BTC', 'ETH', 'LTC']) # data preprocess & record update position_new = position_current average_prices = np.mean(data[:, :4], axis=1) # average price for all assets VAR = [0.5, 0.5, 0.5, 0.5] # Prediction for var model RF = [0.5, 0.5, 0.5, 0.5] # Prediction for Random Forest LR = [0.5, 0.5, 0.5, 0.5] # Prediction for Logistic regression XGB = [] LSTM = [] if total_balance >= init_cash * (1 + EXPECT_RETURN_RATE): memory.is_satisfied = True else: memory.is_satisfied = False ############# rf, var, boost classification ############# if ((counter + 1) % DECISION_PERIOD == 0): bar = [] for i in range(4): memory.data_save_index[i].loc[DECISION_PERIOD - 1] = data[i, ] line = generate_bar(memory.data_save_index[i]) bar.append(line) memory.data_cryp[i] = pd.concat((memory.data_cryp[i], line), axis=0, sort=True) memory.data_cryp[i] = memory.data_cryp[i].reset_index(drop=True) price = [] for t in range(DECISION_PERIOD): for i in range(4): time_price = memory.data_save_index[i].loc[t] time_price_mean = (time_price['close'] + time_price['high'] + time_price['low'] + time_price['open']) / 4 price.append(time_price_mean) price = np.array(price) price = price.reshape(1, 240) LR = [] for m in boost_models: LR.append(m.predict(price)) open_ave = np.array([ bar[0]['open_ave'].values[0], bar[1]['open_ave'].values[0], bar[2]['open_ave'].values[0], bar[3]['open_ave'].values[0] ]) hourly_data = pd.DataFrame(data=[open_ave], columns=['BCH', 'BTC', 'ETH', 'LTC']) memory.hourly_var = pd.concat([memory.hourly_var, hourly_data], ignore_index=True) lag_order = var_model.k_ar if lag_order < len(memory.hourly_var.index): diff = np.log(memory.hourly_var).diff().dropna() X = diff.values[-lag_order:] pred = var_model.forecast(X, 2) baseline = 0 for i in [0, 1, 2, 3]: if i == 1: VAR[i] = -1 continue if (pred[0][i] > baseline and pred[1][i] > baseline): VAR[i] = 1 if (pred[0][i] < (0 - baseline) and pred[1][i] < (0 - baseline)): VAR[i] = 0 else: for i in range(4): memory.data_save_index[i].loc[(counter + 1) % DECISION_PERIOD - 1] = data[i, ] df_cryp_sp = [] for i in range(4): df_cryp = memory.data_cryp[i].copy() if len(df_cryp) > 1: df_cryp['rate'] = (df_cryp['close'] - df_cryp['open']) / df_cryp['open'] volume = pd.DataFrame(df_cryp['volume'][0:len(df_cryp) - 1], columns=['volume']) df_cryp = df_cryp.drop(0).reset_index(drop=True) df_cryp['dVolume'] = abs( (df_cryp['volume'] - volume['volume']) / volume['volume']) df_cryp = df_cryp[['rate', 'dVolume']] rateName = 'rate_' + ASSETS_NAME[i] dVolumeName = 'dVolume_' + ASSETS_NAME[i] df_cryp.columns = [rateName, dVolumeName] df_cryp_sp.append(df_cryp) memory.data_cryp[i] = memory.data_cryp[i].drop(0).reset_index( drop=True) if df_cryp_sp: cryp_data = pd.DataFrame() for cryp in df_cryp_sp: cryp_data = pd.concat((cryp_data, cryp), axis=1) memory.hourly_rf = pd.concat((memory.hourly_rf, cryp_data), axis=0).reset_index(drop=True) if len(memory.hourly_rf) > 2: df_hourly = memory.hourly_rf.copy() for name in ASSETS_NAME: bins = [-1, -0.005, 0.01, 1] group_name = ['down', 'middle', 'up'] predName = 'pred_' + name rateName = 'rate_' + name df_hourly[predName] = pd.cut(df_hourly[rateName], bins, labels=group_name) bins_volume = [0, 2.01, 100] group_volume_name = ['flat', 'sharp'] dVolumeName = 'dVolume_' + name df_hourly[dVolumeName] = pd.cut(df_hourly[dVolumeName], bins_volume, labels=group_volume_name) df_hourly = df_hourly[[ 'pred_BCH', 'pred_BTC', 'pred_ETH', 'pred_LTC', 'dVolume_BCH', 'dVolume_BTC', 'dVolume_ETH', 'dVolume_LTC' ]] df_cryp_t0 = pd.DataFrame(df_hourly.loc[0:len(memory.hourly_rf) - 3]) df_cryp_t0.columns = [ 'BCH_t0', 'BTC_t0', 'ETH_t0', 'LTC_t0', 'dV_BCH_t0', 'dV_BTC_t0', 'dV_ETH_t0', 'dV_LTC_t0' ] df_cryp_t0 = df_cryp_t0.reset_index(drop=True) df_cryp_t1 = pd.DataFrame(df_hourly.loc[1:len(memory.hourly_rf) - 2]) df_cryp_t1.columns = [ 'BCH_t1', 'BTC_t1', 'ETH_t1', 'LTC_t1', 'dV_BCH_t1', 'dV_BTC_t1', 'dV_ETH_t1', 'dV_LTC_t1' ] df_cryp_t1 = df_cryp_t1.reset_index(drop=True) df_hourly = df_hourly.drop([0, 1]).reset_index(drop=True) df_hourly = pd.concat((df_hourly, df_cryp_t0), axis=1) df_hourly = pd.concat((df_hourly, df_cryp_t1), axis=1) X_train = df_hourly.drop( columns=['pred_BCH', 'pred_BTC', 'pred_ETH', 'pred_LTC']) X_train = pd.get_dummies(X_train) y = [] for m in rf_models: y.append(m.predict(X_train)) for i in range(4): if y[i] == 'up': RF[i] = 1 elif y[i] == 'down': RF[i] = 0 else: RF[i] = -1 memory.hourly_rf = memory.hourly_rf.drop(0).reset_index(drop=True) # xgboost & LSTM # for each asset do the predict and make deal. for asset_index in range(4): # when achieving target income, stop making deals # TODO: OR when is_satisfied is true & next prediction is opposite result, clean position for more income if memory.is_satisfied: position_new[asset_index] = 0 continue asset_name = ASSETS[asset_index] # fluctuate_volumn = FLUCTUATE_VOLUMNS[asset_index] deal_unit = DEAL_UNITS[asset_index] average_price = average_prices[asset_index] memory.data_save_name[asset_name].loc[counter] = data[asset_index, ] # predict in DECISION_PERIOD if ((counter + 1) % DECISION_PERIOD == 0 and counter > 60): # Risk Ananlysis if check_balance_warning(cash_balance, crypto_balance, total_balance, CASH_BALANCE_LOWER_LIMIT): continue # Model Evaluation if len(memory.deal_save[asset_name]) > 0: last_deal = memory.deal_save[asset_name][-1] else: last_deal = None # if decision_count > 150 and (failed_count*1.0) / decision_count > 0.7 and not is_reverse: if last_deal and int( memory.data_save_name[asset_name].iloc[-DECISION_PERIOD] ['open'] / memory.data_save_name[asset_name].iloc[-1]['close'] ) == last_deal.prediction: memory.success_count[asset_name] += 1 else: memory.models_cof[ asset_index] -= 0.01 # TODO better strategy needed if ((counter + 1) % (DECISION_PERIOD * 24 * 2) == 0): decision_count = int((counter + 1) / DECISION_PERIOD) if memory.success_count[asset_name] / decision_count <= 0.5: # memory.use_model[asset_index] = False print( f'Not trust {asset_name} model now, but still use it') # Do prediction: use model to predict or not if memory.use_model[asset_index]: ''' What should do here: load data for specified asset from memory.data_save[asset_name] transform data format according to diff models call model predict ensemble result give final prediction: 1: increasing, 0: decreasing, 2: hold the line (it's no matter without 2) ''' # xgboost bar_x = generate_avg_bar(memory.data_save_name[asset_name], barlength=BAR_LENGTH) x_1 = [] for j in range(4): start = int(BAR_LENGTH * j / 4) end = int(BAR_LENGTH * (j + 1) / 4) x_1.append(bar_x.values[start:end, 0].mean()) y1 = xgb_models[asset_index][0].predict(x_1) y2 = xgb_models[asset_index][1].predict(x_1) y3 = xgb_models[asset_index][2].predict(x_1) predict_price = (y1 + y2 + y3) / 3 if predict_price > memory.last_prediction['xgb']: XGB = 1 elif predict_price < memory.last_prediction['xgb']: XGB = 0 else: XGB = -1 memory.last_prediction['xgb'] = predict_price # lstm bar_x = generate_avg_bar(memory.data_save_name[asset_name], barlength=BAR_LENGTH) bar_x = np.array([bar_x[['avg']].values[:, 0]]) x_2 = np.reshape(bar_x, (bar_x.shape[0], 1, bar_x.shape[1])) predict_price = lstm_models[asset_index].predict(x_2) if predict_price >= memory.last_prediction['lstm']: LSTM = 1 elif predict_price < memory.last_prediction['lstm']: LSTM = 0 else: LSTM = -1 memory.last_prediction['lstm'] = predict_price else: # NOT sure is it a better way to replacce model prediction position_new[asset_index] = 0 continue price_pred = [ LR[asset_index], VAR[asset_index], RF[asset_index], XGB, LSTM ] if price_pred.count(1) >= 2 and price_pred.count(0) <= 1: prediction = 1 elif price_pred.count(0) >= 2 and price_pred.count(1) <= 1: prediction = 0 else: prediction = -1 # TODO: consider transaction fee and calculate income rate to refine deal unit if prediction == LONG: deal_type = 'long' if position_new[asset_index] > 0: position_new[asset_index] += int( deal_unit * memory.models_cof[asset_index]) # Assume that new open = last close or avg memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price elif position_new[asset_index] == 0: position_new[asset_index] += int( deal_unit * memory.models_cof[asset_index]) memory.turning_price[asset_name] = average_price memory.invested_balance[asset_name] += int( deal_unit * memory.models_cof[asset_index]) * average_price else: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 elif prediction == SHORT: deal_type = 'short' if position_new[asset_index] < 0: position_new[asset_index] -= int( deal_unit * memory.models_cof[asset_index]) memory.invested_balance[asset_name] -= int( deal_unit * memory.models_cof[asset_index]) * average_price elif position_new[asset_index] == 0: position_new[asset_index] -= int( deal_unit * memory.models_cof[asset_index]) memory.turning_price[asset_name] = average_price memory.invested_balance[asset_name] -= int( deal_unit * memory.models_cof[asset_index]) * average_price else: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 elif prediction == HOLD: # HOLD deal_type = 'none' # record deal deal_price = memory.data_save_name[asset_name].iloc[-1][ 'close'] # unknown yet, for now just a assumed close price in this minute deal = Deal_record(amount=int(deal_unit * memory.models_cof[asset_index])) deal.prob_pred = memory.models_cof[asset_index] deal.asset_index = asset_index # deal.goal_price = deal_price + (1 if deal_type == 'long' else -1) * (PRIOR_WEIGHT * PRIOR + confidence) * fluctuate_volumn deal.deal_type = deal_type deal.prediction = prediction memory.deal_save[asset_name].append(deal) elif (counter != 0): # not decision period & not the first minute # if current currency price can give double expect return, clean position return_rate = get_income_rate(position_new[asset_index], memory.invested_balance[asset_name], average_price, transaction) if return_rate >= EXPECT_DEAL_RETURN / 2: position_new[asset_index] = 0 memory.invested_balance[asset_name] = 0 # End of strategy return position_new, memory
def handle_bar(counter, # a counter for number of minute bars that have already been tested time, # current time in string format such as "2018-07-30 00:30:00" data, # data for current minute bar (in format 2) init_cash, # your initial cash, a constant transaction, # transaction ratio, a constant cash_balance, # your cash balance at current minute crypto_balance, # your crpyto currency balance at current minute total_balance, # your total balance at current minute position_current, # your position for 4 crypto currencies at this minute memory # a class, containing the information you saved so far ): # Here you should explain the idea of your strategy briefly in the form of Python comment. # You can also attach facility files such as text & image & table in your team folder to illustrate your idea # The idea of my strategy: # Make use of some technical patterns in candlestick plots: # Pattern for long signal: (unstrict) three white soldiers # For three sequential bars (each bar is 15 minutes long), if they have the pattern "white soldiers", i.e. # 1. OPEN(n) > OPEN(n-1) # 2. CLOSE(n) > CLOSE(n-1) # 3. CLOSE(n) > OPEN(n) # then we long 1 BTC at next bar unless the current cash balance is less than 30,000 # stop loss point: When the price drop down to the close price of the first white soilder, clear all long position # target profit point: When the price go up to (1+5%) times the close price of the third white soilder, clear all long position # Pattern for short signal: (unstrict) three black craws # For three sequential bars (each bar is 15 minutes long), if they have the pattern "black craws", i.e. # 1. OPEN(n) < OPEN(n-1) # 2. CLOSE(n) < CLOSE(n-1) # 3. CLOSE(n) < OPEN(n) # then we short 1 BTC at next bar unless the current cash balance is less than 30,000 # stop loss point: When the price go up to the close price of the first black craw, clear all short position # target profit point: When the price go up to (1-5%) times the close price of the third black craw, clear all long position # Get position of last minute position_new = position_current # Generate OHLC data for every 15 minutes if counter == 0: memory.data_list = list() memory.bar_prev = np.array([None]) memory.ws_check_table = np.empty((0,2)) memory.bc_check_table = np.empty((0,2)) memory.long_stop_loss = np.inf memory.long_profit_target = np.inf memory.short_stop_loss = np.inf memory.short_profit_target = np.inf if (counter + 1) % bar_length == 0: memory.data_list.append(data) bar = generate_bar(memory.data_list) memory.data_list = list() # Clear memory.data_list after bar combination if memory.bar_prev.any()!=None: ws_check = white_soider(bar, memory.bar_prev, asset_index) memory.ws_check_table = np.append(memory.ws_check_table, [ws_check], axis=0) bc_check = black_craw(bar, memory.bar_prev, asset_index) memory.bc_check_table = np.append(memory.bc_check_table, [bc_check], axis=0) bar_num = len(memory.ws_check_table) if bar_num>3: ''' long signal When there is a three white soider signal, long 1 BTC at next minute unless the current cash balance is less than my_cash_balance_lower_limit ''' if np.sum(memory.ws_check_table[(bar_num-3):bar_num,1])==3: if cash_balance > my_cash_balance_lower_limit: position_new[asset_index] += 1. memory.long_stop_loss = memory.ws_check_table[bar_num-3,0] memory.long_profit_target = memory.ws_check_table[bar_num-1,0]*(1+.05) ''' short signal When there is a three black craw signal, short 1 BTC at next minute unless the current cash balance is less than my_cash_balance_lower_limit ''' if np.sum(memory.bc_check_table[(bar_num-3):bar_num,1])==3: if cash_balance > my_cash_balance_lower_limit: position_new[asset_index] -= 1. memory.short_stop_loss = memory.bc_check_table[bar_num-3,0] memory.short_profit_target = memory.bc_check_table[bar_num-1,0]*(1-.05) memory.bar_prev = bar # save minute data to data_list else: memory.data_list.append(data) # Close signal # When reach stop loss/target profit points, clear all long/short positions average_price = np.mean(data[asset_index,:4]) if(position_new[asset_index] > 0): if average_price > memory.long_profit_target or average_price < memory.long_stop_loss: position_new[asset_index] = 0. else: if average_price > memory.short_stop_loss or average_price < memory.short_profit_target: position_new[asset_index] = 0. # End of strategy return position_new, memory