Esempio n. 1
0
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():
        pass

    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)     # deal pri

        memory.is_satisfied = False     # If True, stop to make deal
        memory.models_cof = [1 for i in range(len(model_list))]     # confidence for each model
        memory.use_model = [True for i in range(len(model_list))]   # use model or not (this is for ensembled model)

        memory.success_count = dict.fromkeys(ASSETS, 0)
    
    # data preprocess & record update
    position_new = position_current
    average_prices = np.mean(data[:, :4], axis=1)       # average price for all assets

    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 % DECISION_PERIOD] = 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
            last_deal = memory.deal_save[asset_name][-1]
            # if decision_count > 150 and (failed_count*1.0) / decision_count > 0.7 and not is_reverse:
            if int(memory.data_save[asset_name][0]['open']/memory.data_save[asset_name][-1]['close']) == last_deal.prediction:
                memory.success_count[asset_name] += 1
            else:
                memory.models_cof[asset_name] -= 0.01   # TODO better strategy needed
            if ((counter+1) % (DECISION_PERIOD*24*2) == 0):
                decision_count = int((counter+1) / DECISION_PERIOD)
                memory.use_model[asset_name] = False if memory.success_count[asset_name] / decision_count <= 0.5 else True

            # 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)
                '''
                prediction = 1      # 1 or 0 or other value
            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

            # 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_name])
                elif position_new[asset_index] == 0:
                    position_new[asset_index] += int(deal_unit * memory.models_cof[asset_name])
                    memory.turning_price[asset_name] = average_price
                else:
                    position_new[asset_index] = 0
            elif prediction == SHORT:
                deal_type = 'short'
                if position_new[asset_index] <= 0:
                    position_new[asset_index] -= int(deal_unit * memory.models_cof[asset_name])
                elif position_new[asset_index] == 0:
                    position_new[asset_index] -= int(deal_unit * memory.models_cof[asset_name])
                    memory.turning_price[asset_name] = average_price
                else:
                    position_new[asset_index] = 0
            else: # HOLD
                deal_type = 'none'

            # record deal
            deal_price = memory.data_save[asset_name][-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_name]))
            deal.prob_pred = memory.models_cof[asset_name]
            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
            deal.has_selled = False
            deal.has_brought = False
            memory.deal_save.append(deal)
        
        elif(counter != 0):   # not decision period & not the first minute
            # if current currency price can give double expect return, clean position
            if (position_new[asset_index] > 0) and (average_price >= memory.turning_price[asset_name]*(1+2*EXPECT_RETURN_RATE)):
                position_new[asset_index] = 0
            if (position_new[asset_index] < 0) and (average_price <= memory.turning_price[asset_name]*(1-2*EXPECT_RETURN_RATE)):
                position_new[asset_index] = 0
            
    # End of strategy
    return position_new, memory
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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