Esempio n. 1
0
        def get_coin_data(self, ptime, symbol):
            """
            coin data from redis by ptime and symbol
            :param ptime:string
            :param symbol:
            :return:
            """
            if self.__df is None:
                raise Exception(
                    'Please call init_data before using get_coin_data')

            try:
                return True, self.__df.loc[symbol, ptime]
            except KeyError as e:
                logger.warning(
                    "(KeyError) There is no {} for {} (human date {}), error: {}"
                    .format(symbol, ptime,
                            TimeHelper.epoch_to_date_time(ptime), e))
                return False, []
            except TypeError as e2:
                logger.warning(
                    "(TypeError) There is no {} for {} (human date {}), error: {}"
                    .format(symbol, ptime,
                            TimeHelper.epoch_to_date_time(ptime), e2))
                return False, []
Esempio n. 2
0
def run(path_to_data_file, current_time=TimeHelper.current_time_stamp(), tick_time_hours=Consts.TICK_TIME_HOURS,
        benchmark_symbols_list=None):
    """
    1) fetch data from files - 1.a. simulation params 1.b. fees 1.c. ml result
    2) run multiprocess all simulation
    3) concate all result(analytics) files from simulation.
    :param id:
    :param tick_time_hours:
    :param benchmark_symbols_list:
    :return:
    """
    if benchmark_symbols_list is None:
        benchmark_symbols_list = [['BTC']]
    # Anlayze results
    logger.info("Getting alto results")
    df_ml_results, df_simulations = LoaderHelper.fetch_simulations(benchmark_symbols_list, path_to_data_file)
    _fees = Fees.Fees()

    # Multi proccesing to run simulation classes which writes results into Simulator/Results/{id}
    data_for_run = []
    df_simulations.index.names = ['index']
    gb = df_simulations.groupby('index')
    for _df in [gb.get_group(x) for x in gb.groups]:
        data_for_run.append((df_ml_results, _df, tick_time_hours, _fees, current_time, benchmark_symbols_list))

    pbar = tqdm(total=len(data_for_run))

    def print_progress(res):
        pbar.update()

    with multiprocessing.Pool(multiprocessing.cpu_count()) as p:
        print(data_for_run)
        res = [p.apply_async(Simulation.Simulation, args=(_single_run,), callback=print_progress) for _single_run in
               data_for_run]
        for func_res in res:
            func_res.get()
        p.close()
        p.join()
    pbar.close()

    path_to_analytics = os.path.join(Consts.PATH_TO_WRITE_RESULT, TimeHelper.epoch_to_date_time(
        current_time).strftime(
        Consts.WRITE_DATE_FORMAT), 'analytics')

    analytics_files = os.listdir(path_to_analytics)
    list_analytics_files_dfs = []
    for file_name in analytics_files:
        list_analytics_files_dfs.append(pd.read_csv(os.path.join(path_to_analytics, file_name)))

    all_analytics_files_df = pd.concat(list_analytics_files_dfs, ignore_index=True, sort=True)
    path_to_write_summery = os.path.join(path_to_analytics, 'Simulations__Summery__Analytics.csv')
    all_analytics_files_df.set_index('simulation_id', inplace=True)
    all_analytics_files_df.to_csv(path_to_write_summery)
    logger.info('Finished all simlations, base path result:{}, analytics summery: {}'.format(os.path.join(Consts.PATH_TO_WRITE_RESULT, TimeHelper.epoch_to_date_time(
        current_time).strftime(
        Consts.WRITE_DATE_FORMAT)), path_to_write_summery))
Esempio n. 3
0
def fetch_simulations(benchmark_symbols_list, path_to_data_file):
    """
    init coins data to redis
    Creates 3 dataframe 1.MLResult. 2.all simulation params options. 3. fees
    a data frame with index as simulation_id and the following columns:
    [amount_of_capital, max_percante_cap_invested_in_a_round, max_percentage_out_of_volume,
    :return: params, ml_results, prices
    """
    # benchmark_symbols_list, can be list in a list so this how i'm init all coins data to redis
    list_coins_to_init = []
    for temp_obj in benchmark_symbols_list:
        if not isinstance(temp_obj, list):
            list_coins_to_init.append(temp_obj)
            continue
        list_coins_to_init += temp_obj

    ml_results = pd.concat([
        load_ml_results(Consts.ML_RESULT_LONG_PATH, Consts.LONG),
        load_ml_results(Consts.ML_RESULT_SHORT_PATH, Consts.SHORT)
    ],
                           ignore_index=True,
                           sort=True)

    ml_results['prediction_time'] = pd.to_datetime(
        ml_results['prediction_time'], format=Consts.READ_DATE_FORMAT).apply(
            lambda x: TimeHelper.datetime_to_epoch(x))
    simulations_options_df = load_simulation_params()

    _data_helper.init_data(
        list(set(list_coins_to_init).union(set(ml_results.coin_symbol))),
        path_to_data_file, ml_results['prediction_time'].min(),
        ml_results['prediction_time'].max())

    convert_dfs_int_to_float([ml_results, simulations_options_df])
    return [ml_results, simulations_options_df]
Esempio n. 4
0
 def advance_one_step(self):
     """
     Advances current time by ticktime interval
     :return:
     """
     self.current_time += (self.hours_tick_time_interval * 60 * 60)
     logger.debug("Simulation has advance to time {}".format(
         TimeHelper.epoch_to_date_time(self.current_time)))
Esempio n. 5
0
    def __init__(self, coin_symbol, order_type, time_ticker, positive_target,
                 negative_target, capital, trailing, fees, leverage_capital,
                 apply_leverage_fees_on_all_capital, leverage,
                 long_trailing_strategy, short_trailing_strategy, time_predict,
                 active_long_investment_strategy,
                 active_short_investment_strategy):
        self.coin_symbol = coin_symbol  # name of the coin
        self.order_type = order_type  # position is short or long
        self.initial_time = time_ticker.current_time  # the timestamp the position has been opened
        self.active = True  # position status
        self.position_end_time = None  # time position finished
        self.position_life_time = time_predict
        self.initial_position_life_time = time_predict
        self.positive_target = positive_target
        self.negative_target = negative_target
        self.current_capital = capital
        self.initial_capital = capital
        self.trailing = trailing  # Boolean
        self.buy_price = []
        self.last_price = None
        self.hit_profit_target = False
        self.hit_loss_target = False
        self.expired = False
        self.stopped = False
        self.liquidated = False
        self.trailing_activated = 0
        self.long_trailing_strategy = long_trailing_strategy
        self.short_trailing_strategy = short_trailing_strategy
        self.active_long_investment_strategy = active_long_investment_strategy
        self.active_short_investment_strategy = active_short_investment_strategy
        self.fees = fees
        self.hours_position_open = 0
        self.fees_paid = 0
        self.leverage_capital = leverage_capital
        self.leverage = leverage
        self.time_ticker = time_ticker
        self.apply_leverage_fees_on_all_capital = apply_leverage_fees_on_all_capital

        # Initializes position once created
        self.enter_position()

        logger.debug(
            "{} position for {} in {} has been created successfully with {} capital which includes {} leverage, with the cost of {} fees"
            .format(self.order_type, self.coin_symbol,
                    TimeHelper.epoch_to_date_time(self.initial_time),
                    self.initial_capital, self.leverage_capital,
                    self.fees_paid))
Esempio n. 6
0
    def updates_new_time_is_liquidate(self, ml_results=None):
        """
        Updates capital and hours positions open according to new time
        :return: Boolean if liquidated or not
        """

        # Updates Capital
        success, coins_data = \
            coins_market_data_getter.get_coin_data(int(self.time_ticker.current_time), self.coin_symbol)

        if not success:
            logger.error("No open price for coin {} at time {}".format(
                self.coin_symbol, self.initial_time))
            raise Exception("No open price for coin {} at time {}".format(
                self.coin_symbol, self.initial_time))

        new_price = coins_data['_open']

        # If Long then we profit from positive change and if short we profit from negative change
        if self.order_type == Consts.LONG:
            current_change = (new_price / self.last_price) - 1
        else:
            current_change = ((new_price / self.last_price) - 1) * (-1)

        self.current_capital += (self.current_capital * current_change)

        # Updates last price
        self.last_price = new_price

        # Updates hours position opened
        self.hours_position_open += self.time_ticker.hours_tick_time_interval

        # Check if position got liquidated
        if self.current_capital <= self.leverage_capital:
            logger.error(
                "The position with coin symbol: {} got liquidated at {}".
                format(
                    self.coin_symbol,
                    TimeHelper.epoch_to_date_time(
                        self.time_ticker.current_time)))
            self.liquidated = True
            self.close_position()
            return True
        else:
            return False
Esempio n. 7
0
    def fetch_coins_24h_volumeto(self, coin_symbol):
        """
        Aggregated volumeto for the last 24h
        :param coin_symbol:
        :return: success, volumeto24h
        """
        volumeto = 0
        hours_to_calculate = 25
        counter = 1
        while counter <= hours_to_calculate:
            _time_to_fetch = self.time_ticker.current_time - (counter * 60 *
                                                              60)
            success, coins_market = coins_market_data_getter.get_coin_data(
                int(_time_to_fetch), coin_symbol)
            if not success:
                logger.error(
                    "Skipping coin {}, there is no market data from db in {}".
                    format(coin_symbol,
                           TimeHelper.epoch_to_date_time(_time_to_fetch)))
                raise Exception

            volumeto += coins_market['_volumeto']
            counter += 1
        return True, volumeto
Esempio n. 8
0
                    const=True, default=[['BTC']],
                    help="The coin/coins for benchmark, for 2 benchmarks for BTC and ETH write \"BTC ETH\", "
                         "for 1 benchmark of BTC and ETH (new index) write \"BTC,ETH\". default: \"BTC\".")

parser.add_argument("-resultPath", type=str, nargs='?',
                    const=True, default=os.getcwd(),
                    help="The path to create the results folder. default the working dir.")

parser.add_argument("-AnalyzeExistingResults", type=bool, nargs='?',
                    const=True, default=None,
                    help="take the result of the simulation that already finished. and summarizes it.")

args = parser.parse_args()

if __name__ == '__main__':
    current_time = TimeHelper.current_time_stamp()
    Consts.BENCHMARKS = args.benchmarkCoins
    Consts.set_path_to_write_result(args.resultPath)
    if not args.RunSimulations and not args.AnalyzeExistingResults:
        print("Please select at least one runStage in order to start Manager.")
        quit(1)

    if args.RunSimulations:
        if args.pathToCoinsPrice is None:
            print("Please specify the pathToCoinsPrice.")
            quit(1)
        if not os.path.isfile(args.pathToCoinsPrice):
            print("pathToCoinsPrice does not exist {}.".format(args.pathToCoinsPrice))
            quit(1)
        if not args.pathToCoinsPrice.endswith('.csv.gz'):
            print("pathToCoinsPrice must be csv and gzip compressed.")
Esempio n. 9
0
def start(start_running_time, coins_for_benchmark, df_simulation,
          positions_history, capital_history):
    """
    function "get statistics" was build before in version one. and this function arrange the dataframe to
    be sent to "get statistics" correctly. acc = [{date_time,capital},..],benchmark = [{date_time,capital},..]
    :param simulation_result_with_benchmark: dataframe with acc capital and benchmarks capital example pd.DataFrame(
    #     data={'date_time': ['1483228800', '1483232400', '1483236000', '1483239600'],
    #           'capital': [123, 213, 342, 44324], 'benchmark_BTC': [222, 222, 222, 222],
    :return: dataframe {'subject': ['ACC-BTC', 'ACC-ETH'],
    #                 'alpha': [123, 213, 342, 44324], 'betta': [222, 222, 222, 222],
    #                 'benchmark_ETH': [222, 222, 222, 222], 'rsquared': [222, 222, 222, 222],
    """
    # simulation_result_with_benchmark = pd.DataFrame(
    #     data={'date_time': ['1483228800', '1483232400', '1483236000', '1483239600'],
    #           'capital': [123, 213, 342, 44324], 'benchmark_BTC': [222, 222, 222, 222],
    #           'benchmark_ETH': [222, 222, 222, 222]})
    # final_result1 = {'subject': ['ACC-BTC', 'ACC-ETH'],
    #                 'alpha': [123, 213, 342, 44324], 'betta': [222, 222, 222, 222],
    #                 'benchmark_ETH': [222, 222, 222, 222], 'rsquared': [222, 222, 222, 222],
    #                 'standard_deviation': [222, 222, 222, 222], 'sharp_ratio': [222, 222, 222, 222]}

    path = os.path.join(
        Consts.PATH_TO_WRITE_RESULT,
        TimeHelper.epoch_to_date_time(start_running_time).strftime(
            Consts.WRITE_DATE_FORMAT), str(df_simulation.index[0]))
    os.makedirs(path, exist_ok=True)

    positions_history.to_csv(os.path.join(path, 'positions.csv'), index=False)
    df_simulation.index.names = ['simulation_id']
    df_simulation.to_csv(os.path.join(path, 'simulation.csv'))
    capital_history['date_time'] = pd.to_datetime(
        capital_history['date_time'], format=Consts.READ_DATE_FORMAT).apply(
            lambda x: TimeHelper.datetime_to_epoch(x))
    capital_history['capital'] = capital_history['liquid_capital'] + capital_history['shorts_capital'] + \
                                 capital_history['long_capital']

    # acc_capital = capital_history.drop(capital_history.columns.difference(['capital', 'date_time']), 1).to_dict(
    #     'record')
    acc_capital_with_banchmark_df, benchmark_column_names = add_benchmarks(
        capital_history, coins_for_benchmark,
        df_simulation['amount_of_capital'].iloc[0])

    acc_capital_with_banchmark_df['date_time'] = acc_capital_with_banchmark_df[
        'date_time'].apply(lambda x: TimeHelper.epoch_to_date_time(x))
    acc_capital_with_banchmark_df.set_index('date_time', inplace=True)
    acc_capital_with_banchmark_df.sort_index(inplace=True)
    acc_capital_with_banchmark_df.to_csv(
        os.path.join(path, 'capital_history.csv'))

    analytics_result_list = []
    for column_benchmark in benchmark_column_names:
        temp_obj = get_statistics(
            df_simulation.index[0], 'ACC-{}'.format(column_benchmark),
            acc_capital_with_banchmark_df['capital'].values,
            acc_capital_with_banchmark_df[column_benchmark].values)
        analytics_result_list.append(temp_obj)

    analytics_result_df = pd.DataFrame(data=analytics_result_list)
    analytics_result_df['ACC_ROI'] = (
        acc_capital_with_banchmark_df['capital'].values[-1] /
        acc_capital_with_banchmark_df['capital'].values[0]) - 1

    last_row_capital_history = capital_history.tail(1).copy()
    last_row_capital_history['simulation_id'] = df_simulation.index[0]

    last_row_capital_history.set_index(['simulation_id'], inplace=True)
    analytics_result_df.set_index(['simulation_id'], inplace=True)

    analytics_result_df = analytics_result_df.join(df_simulation).join(
        last_row_capital_history)

    path_to_analytics = os.path.join(
        Consts.PATH_TO_WRITE_RESULT,
        TimeHelper.epoch_to_date_time(start_running_time).strftime(
            Consts.WRITE_DATE_FORMAT), 'analytics')

    os.makedirs(path_to_analytics, exist_ok=True)
    path_to_create_result = os.path.join(
        path_to_analytics,
        'Simulation__{}__Analytics.csv'.format(df_simulation.index[0]))
    analytics_result_df.to_csv(path_to_create_result, index=True)
    logger.info(
        'Finish creating analytics file for simulation ID: {}, you can look in: {}'
        .format(df_simulation.index[0], path_to_create_result))
Esempio n. 10
0
    def capital_allocation_strategy(self, coins_to_invest, available_capital):
        """
        Recursive function which allocates funds according to simulation conditions and then allocates capital according to probability and 24h volume
        :param coins_to_invest:
        :param available_capital:
        :return: coins_to_invest and Adds 'capital_to_invest' column and 'fully_invested' column to each row
        """
        coins_available_capital = 0
        used_capital = 0

        # Count positions which capital size is not equal to max capacity of investment
        total_positions_count = len(
            coins_to_invest[coins_to_invest[Consts.FULLY_INVESTED] == False])

        if total_positions_count > 0:

            # Divide all available capital equally by all the positions
            coins_available_capital = available_capital / total_positions_count

        # Stopping condition: If there are no more position not fully invested or coins_available_capital is smaller then min investment
        if total_positions_count == 0 or coins_available_capital < self.min_investment:
            return coins_to_invest

        # Iterate all coins to invest which are not fully invested
        for index, coins_prediction in coins_to_invest[coins_to_invest[
                Consts.FULLY_INVESTED] == False].copy().iterrows():

            coin_symbol = coins_prediction['coin_symbol']

            success, coin_current_volume = self.fetch_coins_24h_volumeto(
                coin_symbol)

            # exit if failed to fetch volume
            if not success:
                raise Exception

            if coin_current_volume == 0.0:
                logger.debug(
                    "Volume is zero. Not investing in: {}, at time: {}".format(
                        coin_symbol,
                        TimeHelper.epoch_to_date_time(
                            self.time_ticker.current_time)))
                coins_to_invest.loc[index, Consts.FULLY_INVESTED] = True
                continue

            # Volume boundary of the specific coin symbol at the specific time
            coins_max_capital_volume_boundary = self.max_percent_out_of_volume * coin_current_volume

            # If the volume boundary is smaller then available capital, then there is maximum capital in current position means = fully invested
            if coins_max_capital_volume_boundary < coins_available_capital:
                coins_to_invest.loc[index, Consts.FULLY_INVESTED] = True
                max_amount_to_invest_in_coin = coins_max_capital_volume_boundary
            else:
                max_amount_to_invest_in_coin = coins_available_capital

            # Risk indicator which decreases positions size according to probability
            capital_percent = self.percent_capital_according_to_probability(
                coins_prediction[Consts.PROB_POSITIVE_HEADER],
                coins_prediction[Consts.PROB_NEGATIVE_HEADER],
                coins_prediction['order_type'])

            current_capital_to_invest_in_position = capital_percent * max_amount_to_invest_in_coin

            # Add to capital to invest for current row
            coins_to_invest.loc[
                index, Consts.CAPITAL_TO_INVEST] = coins_to_invest.loc[
                    index, Consts.
                    CAPITAL_TO_INVEST] + current_capital_to_invest_in_position

            used_capital += current_capital_to_invest_in_position

        available_capital -= used_capital

        return self.capital_allocation_strategy(coins_to_invest,
                                                available_capital)
Esempio n. 11
0
    def invest(self, new_positions):
        """
        Invests in new positions.
        :param new_positions: df
        :return:
        """

        # Add three columns to df and initialize
        new_positions.loc[:, Consts.FULLY_INVESTED] = False
        new_positions.loc[:, Consts.CAPITAL_TO_INVEST] = 0
        new_positions.loc[:, Consts.LEVERAGED_CAPITAL] = 0

        # Available capital for current round
        available_capital = self.liquid_capital * self.max_percent_cap_investment_in_a_round

        if available_capital < self.min_investment:
            logger.debug(
                "The available capital for this round is smaller then the min investment. There are no new positions for time:{}"
                .format(
                    TimeHelper.epoch_to_date_time(
                        self.time_ticker.current_time)))
            return

        # Adds 'capital_to_invest' column and 'fully_invested' column to each row
        new_positions = self.capital_allocation_strategy(
            new_positions, available_capital)

        if len(new_positions) == 0:
            logger.debug("There are no new positions for time:{}".format(
                TimeHelper.epoch_to_date_time(self.time_ticker.current_time)))
            return

        # If simulation has leverage, fills Consts.LEVERAGE_CAPITAL with relevant leverage
        if self.leverage > 1:
            new_positions = self.add_leverage_by_conditions(new_positions)

        # Create new positions
        for index, position in new_positions.iterrows():
            order_type = position['order_type']

            # Create a new position
            pos = Position.Position(
                position['coin_symbol'], order_type, self.time_ticker,
                position['high_boundary'], position['low_boundary'],
                position['capital_to_invest'] +
                position[Consts.LEVERAGED_CAPITAL], self.trailing_strategy,
                self.fees, position[Consts.LEVERAGED_CAPITAL],
                self.apply_leverage_fees_on_all_capital, self.leverage,
                self.long_trailing_strategy, self.short_trailing_strategy,
                position['time_predict'], self.active_long_investment_strategy,
                self.active_short_investment_strategy)

            # Allocates each order to its relevant statistics
            if order_type == Consts.SHORT:
                self.active_short_positions.append(pos)
                self.short_capital += pos.get_current_liquid_capital()
            else:
                self.active_long_positions.append(pos)
                self.long_capital += pos.get_current_liquid_capital()

            # Update portfolio liquid capital and leverage capital
            self.liquid_capital -= pos.get_current_liquid_capital()
            self.leverage_capital += pos.leverage_capital

        logger.debug("Finished investment cycle for time {}".format(
            TimeHelper.epoch_to_date_time(self.time_ticker.current_time)))
        logger.debug(
            "liquid capital: {}, leverage capital: {}, long capital: {}, short capital: {}"
            .format(self.liquid_capital, self.leverage_capital,
                    self.long_capital, self.short_capital))
Esempio n. 12
0
    def enter_new_positions(self, current_ml_results):
        """"
        Iterates MLResults and handles each one
        :param current_ml_results: df
        :return: None
        """

        # If we simulation does not accept short and long positon on the same coin at the same time
        if not self.accept_short_and_long_same_tick_and_symbol:
            current_ml_results = current_ml_results.drop_duplicates(
                'coin_symbol')

        if not self.longs:
            current_ml_results = current_ml_results[
                current_ml_results['order_type'] != Consts.LONG]

        if not self.shorts:
            current_ml_results = current_ml_results[
                current_ml_results['order_type'] != Consts.SHORT]

        index_to_delete = []
        # Iterate ml results and add to new_positions accordingly
        for index, row in current_ml_results.copy().iterrows():

            # Skip prediction if simulation is limited to invest in specific coins. Notice, if the list is ALL then the simulation has no limitations.
            coin_symbol = row['coin_symbol']

            success, coin_current_volume = self.fetch_coins_24h_volumeto(
                coin_symbol)

            # exit if failed to fetch volume
            if not success:
                raise Exception

            # Volume boundary of the specific coin symbol at the specific time
            coins_max_capital_volume_boundary = self.max_percent_out_of_volume * coin_current_volume

            # Not enough volume to invest
            if coins_max_capital_volume_boundary < self.min_investment:
                logger.warning(
                    "Not enough volume to invest in {} at {}".format(
                        coin_symbol,
                        TimeHelper.epoch_to_date_time(
                            self.time_ticker.current_time)))
                index_to_delete.append(index)
                continue

            prob_positive = row[Consts.PROB_POSITIVE_HEADER]
            prob_negative = row[Consts.PROB_NEGATIVE_HEADER]

            # Check if we should invest long according to long investment strategy then remain in df. If not, deletes the prediction from current_ml_results
            if row['order_type'] == Consts.LONG and not self.is_long_according_to_invest_strategy(
                    prob_positive, prob_negative):
                index_to_delete.append(index)

            # Check if we should invest short according to short investment strategy then remain. If not, deletes the prediction from current_ml_results
            elif row[
                    'order_type'] == Consts.SHORT and not self.is_short_according_to_invest_strategy(
                        prob_positive, prob_negative):
                index_to_delete.append(index)
        current_ml_results.drop(index_to_delete, inplace=True)
        # There are no new positions
        if len(current_ml_results) == 0:
            logger.debug(
                "There are no new positions according to current strategy, at time: {}"
                .format(
                    TimeHelper.epoch_to_date_time(
                        self.time_ticker.current_time)))
        else:
            self.invest(current_ml_results)
Esempio n. 13
0
    def run(self):
        """
        Runs simulation with the following order:
        0. Updates all run according to new time.
        1. Apply hourly fees if exist
        2. Check if positions reached the high or low target and close/trail them accordingly
        3. Check if positions expired and close accordingly
        4. Apply active positions strategy on all open positions and close accordingly
        5. Check if there are new MLResults and invest accordingly

        At the end of the run, creates 3 files for each simulation and 1 file which aggregates all together: ( path = /opt/simulation
        a. capital_history.csv - the status of the portfolio every tick time.
        b. positions.csv - all the positions for the simulation.
        c. simulation.csv - documentation of all params of the simulation.
        :return:
        """

        logger.info('Starting simulation ID: {}'.format(
            self.df_simulation.index[0]))

        # Start time is according to oldest ML result
        start_timestamp, end_timestamp = self.simulation_time_interval()

        # Create a time ticker for simulation
        self.time_ticker = TimeTicker.TimeTicker(start_timestamp,
                                                 self.tick_time_hours)

        # Initial Portfolio
        active_portfolio = Portfolio.Portfolio(self.df_simulation, self.fees,
                                               self.time_ticker)

        # Loop according to tick time, while there are still positions open or while there are still MLResults left to iterate
        while self.time_ticker.current_time < end_timestamp:

            # Update portfolio according to new time for next round
            active_portfolio.updater(Consts.UPDATES_NEW_TIME_IS_LIQUIDATE)

            # If There are leveraged positions, decrease fees
            active_portfolio.apply_time_leverage_fees()

            # If active positions, update them
            if active_portfolio.is_there_open_positions():
                active_portfolio.updater(Consts.REACH_TARGET_UPDATE)
                active_portfolio.updater(Consts.IS_EXPIRED)

            # Fetch ml results for
            current_ml_results = self.ml_results_df.loc[
                self.ml_results_df['prediction_time'] ==
                self.time_ticker.current_time]

            if len(current_ml_results) == 0:
                self.hours_with_no_predictions += 1

            # Filter according to coin_to_invest
            if self.coins_to_invest[0] != Consts.ALL:
                current_ml_results = current_ml_results.loc[
                    self.ml_results_df['coin_symbol'].isin(
                        self.coins_to_invest)]

            # If there is MLResult in current time
            if len(current_ml_results) > 0:
                active_portfolio.updater(Consts.IS_ACTIVE_INVEST_STRATEGY,
                                         ml_results=current_ml_results)
                active_portfolio.enter_new_positions(current_ml_results)

            # Update capital history
            self.capital_history = self.capital_history.append(
                pd.DataFrame(
                    data={
                        'date_time': [
                            TimeHelper.epoch_to_date_time(
                                self.time_ticker.current_time)
                        ],
                        'liquid_capital': [active_portfolio.liquid_capital],
                        'shorts_capital': [active_portfolio.short_capital],
                        'long_capital': [active_portfolio.long_capital],
                        'leverage_capital':
                        [active_portfolio.leverage_capital],
                        'fees_paid': [active_portfolio.fees_paid],
                        'miss_positions': [active_portfolio.miss_positions],
                        'hit_positions': [active_portfolio.hit_positions],
                        'stopped_positions':
                        [active_portfolio.stopped_positions_counter],
                        'expired_positions':
                        [active_portfolio.expired_positions_counter],
                        'hit_trail_positions':
                        [active_portfolio.hit_trail_positions],
                        'hours_with_no_predictions':
                        [self.hours_with_no_predictions],
                        'total_number_of_active_positions': [
                            len(active_portfolio.active_long_positions +
                                active_portfolio.active_short_positions)
                        ]
                    }),
                ignore_index=True,
                sort=True)

            # Advance current_timestamp
            self.time_ticker.advance_one_step()

        # Closing all open positions
        if active_portfolio.is_there_open_positions():
            logger.info("There are open positions, closing all")
            active_portfolio.updater(Consts.FORCE_CLOSE_ALL_POSITIONS)

        logger.info('Creating analytics file for simulation ID: {}'.format(
            self.df_simulation.index[0]))
        positions_history = self.fetch_positions_history_df(active_portfolio)
        AnalyticsFactory.start(self.start_running_time,
                               self.coins_for_benchmark, self.df_simulation,
                               positions_history, self.capital_history)

        logger.info('end of simulation ID: {}'.format(
            self.df_simulation.index[0]))
Esempio n. 14
0
    def fetch_positions_history_df(self, active_portfolio):
        """
        creates a df of all the positions in the simulation
        :param active_portfolio:
        :return: df of positions histroy
        """

        positions_history = pd.DataFrame(
            data={
                'initial_time': [],
                'end_time': [],
                'coin_symbol': [],
                'order_type': [],
                'life_time_in_hours': [],
                'positive_target': [],
                'negative_target': [],
                'initial_capital_include_leverage': [],
                'final_capital': [],
                'buy_price': [],
                'last_price': [],
                'hit_profit_target': [],
                'hit_loss_target': [],
                'expired': [],
                'stopped': [],
                'liquidated': [],
                'trailing_activated': [],
                'hours_position_open': [],
                'fees_paid': [],
                'leverage_capital': [],
                'leverage': [],
                'ROI': []
            })
        for pos in active_portfolio.closed_long_positions + active_portfolio.closed_short_positions:
            positions_history = positions_history.append(pd.DataFrame(
                data={
                    'initial_time':
                    [TimeHelper.epoch_to_date_time(pos.initial_time)],
                    'end_time':
                    [TimeHelper.epoch_to_date_time(pos.position_end_time)],
                    'coin_symbol': [pos.coin_symbol],
                    'order_type': [pos.order_type],
                    'life_time_in_hours': [pos.initial_position_life_time],
                    'positive_target': [pos.positive_target],
                    'negative_target': [pos.negative_target],
                    'initial_capital_include_leverage': [pos.initial_capital],
                    'final_capital': [pos.current_capital],
                    'buy_price': [pos.buy_price],
                    'last_price': [pos.last_price],
                    'hit_profit_target': [pos.hit_profit_target],
                    'hit_loss_target': [pos.hit_loss_target],
                    'expired': [pos.expired],
                    'stopped': [pos.stopped],
                    'liquidated': [pos.liquidated],
                    'trailing_activated': [pos.trailing_activated],
                    'hours_position_open': [pos.hours_position_open],
                    'fees_paid': [pos.fees_paid],
                    'leverage_capital': [pos.leverage_capital],
                    'leverage': [pos.leverage],
                    'ROI': [pos.get_roi_status()]
                }),
                                                         ignore_index=True,
                                                         sort=True)
        return positions_history
Esempio n. 15
0
    def reach_target_update(self, ml_results=None):
        """
        Checks if position reached target, and updates accordingly
        :return: Boolean if reach positive or negative target
        """
        success, coins_data = coins_market_data_getter.get_coin_data(
            int(self.time_ticker.current_time), self.coin_symbol)

        if not success:
            raise Exception

        diff_high = ((coins_data['_high'] / self.buy_price[-1]) - 1)
        diff_low = ((coins_data['_low'] / self.buy_price[-1]) - 1)

        if coins_data['_high'] / coins_data['_low'] > 2:
            logger.error(
                "In time {} there was 2 times jump between high and low price for coin {}"
                .format(
                    TimeHelper.epoch_to_date_time(
                        self.time_ticker.current_time), self.coin_symbol))
            self.hit_loss_target += 1
            self.close_position(profit=False)
            return True

        if diff_high >= self.positive_target and diff_low <= self.negative_target:
            logger.error(
                "In time {} the price reached the high and low boundary for coin {}"
                .format(
                    TimeHelper.epoch_to_date_time(
                        self.time_ticker.current_time), self.coin_symbol))
            self.hit_loss_target += 1
            self.close_position(profit=False)
            return True

        # If hits target for short or long
        if (diff_low <= self.negative_target and self.order_type
                == Consts.SHORT) or (diff_high >= self.positive_target
                                     and self.order_type == Consts.LONG):

            # If trailing is on, apply
            if self.trailing:
                if (self.order_type == Consts.SHORT
                        and len(self.short_trailing_strategy) != 0) or (
                            self.order_type == Consts.LONG
                            and len(self.long_trailing_strategy) != 0):
                    self.handle_trailing()
                    return False

            self.close_position(profit=True)
            self.hit_profit_target = True
            return True

        # if miss target for short or long
        elif (diff_high >= self.positive_target and self.order_type
              == Consts.SHORT) or (diff_low <= self.negative_target
                                   and self.order_type == Consts.LONG):
            self.close_position(profit=False)
            self.hit_loss_target = True
            return True

        # Did not reach either targets
        else:
            return False