Example #1
0
 async def private_(self, type_: str, url: str, params: dict = {}) -> dict:
     timestamp = int(time() * 1000)
     params.update({'api_key': self.key, 'timestamp': timestamp})
     for k in params:
         if type(params[k]) == bool:
             params[k] = 'true' if params[k] else 'false'
         elif type(params[k]) == float:
             params[k] = str(params[k])
     params['sign'] = hmac.new(self.secret.encode('utf-8'),
                               urlencode(sort_dict_keys(params)).encode('utf-8'),
                               hashlib.sha256).hexdigest()
     async with getattr(self.session, type_)(self.base_endpoint + url, params=params) as response:
         result = await response.text()
     return json.loads(result)
Example #2
0
def jackrabbit(trades_list: [dict], backtesting_settings: dict, ranges: dict,
               base_filepath: str):

    if backtesting_settings['random_starting_candidate']:
        best = {
            key: calc_new_val((abs(ranges[key][1]) - abs(ranges[key][0])) / 2,
                              ranges[key], 1.0)
            for key in sorted(ranges)
        }
        print('random starting candidate:', best)
    else:
        best = sort_dict_keys({k_: backtesting_settings[k_] for k_ in ranges})

    n_days = backtesting_settings['n_days']
    results = {}
    best_gain = -9e9
    candidate = best

    ks = backtesting_settings['n_jackrabbit_iterations']
    k = backtesting_settings['starting_k']
    ms = np.array([1 / (i / 2 + 16) for i in range(ks)])
    ms = ((ms - ms.min()) / (ms.max() - ms.min()))
    trades_filepath = make_get_filepath(
        os.path.join(base_filepath, 'trades', ''))
    json.dump(backtesting_settings,
              open(base_filepath + 'backtesting_settings.json', 'w'),
              indent=4,
              sort_keys=True)

    print(backtesting_settings, '\n\n')

    while k < ks - 1:

        if candidate['min_markup'] >= candidate['max_markup']:
            candidate['min_markup'] = candidate['max_markup']

        settings_ = {**backtesting_settings, **candidate}
        key = format_dict(candidate)
        if key in results:
            print('\nskipping', key)
            candidate = get_new_candidate(ranges, best)
            continue
        print(f'\nk={k}, m={ms[k]:.4f} candidate:\n', candidate)
        start_time = time()
        trades = backtest(trades_list, settings_)
        print('\ntime elapsed', round(time() - start_time, 1), 'seconds')
        if not trades:
            print('\nno trades')
            candidate = get_new_candidate(ranges, best)
            continue
        k += 1
        tdf = pd.DataFrame(trades).set_index('trade_id')
        tdf.to_csv(trades_filepath + key + '.csv')
        closest_liq = ((tdf.price - tdf.liq_price).abs() / tdf.price).min()
        biggest_pos_size = tdf.pos_size.abs().max()
        n_closes = len(tdf[tdf.type == 'close'])
        pnl_sum = tdf.pnl.sum()
        loss_sum = tdf[tdf.type == 'stop_loss'].pnl.sum()
        abs_pos_sizes = tdf.pos_size.abs()
        gain = (pnl_sum + settings_['balance']) / settings_['balance']
        average_daily_gain = gain**(1 / n_days)
        n_trades = len(tdf)
        result = {
            'n_closes': n_closes,
            'pnl_sum': pnl_sum,
            'loss_sum': loss_sum,
            'average_daily_gain': average_daily_gain,
            'gain': gain,
            'n_trades': n_trades,
            'closest_liq': closest_liq,
            'biggest_pos_size': biggest_pos_size,
            'n_days': n_days
        }
        print('\n\n', result)
        results[key] = {**result, **candidate}

        if gain > best_gain:
            best = candidate
            best_gain = gain
            print('\n\n\n###############\nnew best', best,
                  '\naverage daily gain:', round(average_daily_gain,
                                                 5), '\n\n')
            print(settings_, '\n')
            print(results[key], '\n\n')
            default_live_settings = load_settings(settings_['exchange'],
                                                  print_=False)
            live_settings = {
                k: settings_[k] if k in settings_ else default_live_settings[k]
                for k in default_live_settings
            }
            live_settings['indicator_settings'] = {
                'ema': {
                    'span': best['ema_span']
                }
            }
            json.dump(live_settings,
                      open(base_filepath + 'best_result_live_settings.json',
                           'w'),
                      indent=4,
                      sort_keys=True)
            json.dump(results[key],
                      open(base_filepath + 'best_result.json', 'w'),
                      indent=4,
                      sort_keys=True)
        candidate = get_new_candidate(ranges, best, m=ms[k])
        pd.DataFrame(results).T.to_csv(base_filepath + 'results.csv')
Example #3
0
def jackrabbit(agg_trades: pd.DataFrame):
    '''
    # settings for binance
    settings = {
        "default_qty": 0.001,
        "grid_step": 344,
        "leverage": 125,
        "maker_fee": 0.00018,
        "margin_limit": 60,
        "markups": (0.0038,),
        "min_qty": 0.001,
        "n_close_orders": 1,
        "n_entry_orders": 7,
        "price_step": 0.01,
        "qty_step": 0.001,
        "symbol": "BTCUSDT",
        "inverse": False,
        "break_on_loss": True,
    }
    ranges = {
        'default_qty': (settings['min_qty'], settings['min_qty'] * 1, settings['qty_step']),
        'grid_step': (10, 400, 1),
        'markups': (0.0005, 0.005, 0.0001),
        'n_close_orders': (1, 1, 1),
    }
    '''
    # settings for bybit
    settings = {
        "default_qty": 1.0,
        "grid_step": 344,
        "leverage": 100,
        "maker_fee": -0.00025,
        "margin_limit": 0.001,
        "markups": (0.0038, ),
        "min_qty": 1.0,
        "n_close_orders": 1,
        "n_entry_orders": 7,
        "price_step": 0.5,
        "qty_step": 1.0,
        "symbol": "BTCUSD",
        "inverse": True,
        "break_on_loss": True,
    }
    ranges = {
        'default_qty': (1, 30, 1),
        'grid_step': (1, 400, 1),
        'margin_limit': (0.001, 0.001, 0.0001),
        'markups': (0.0001, 0.01, 0.0001),
        'n_close_orders': (1, 10, 1),
    }

    tweakable = {
        'default_qty': 0.0,
        'grid_step': 0.0,
        'markups': (0.0, 0.0),
        'n_close_orders': 0.0
    }

    best = {}

    for key in tweakable:
        if type(tweakable[key]) == tuple:
            best[key] = tuple(
                sorted([
                    calc_new_val((ranges[key][1] - ranges[key][0]) / 2,
                                 ranges[key], 1.0) for _ in tweakable[key]
                ]))
        else:
            best[key] = calc_new_val((ranges[key][1] - ranges[key][0]) / 2,
                                     ranges[key], 1.0)

    # optional: uncomment to use settings as start candidate.
    #best = {k_: settings[k_] for k_ in sorted(ranges)}

    settings = sort_dict_keys(settings)
    best = sort_dict_keys(best)

    results = {}
    best_gain = -99999999
    candidate = best

    ks = 200
    k = 0
    ms = np.array([1 / (i / 2 + 16) for i in range(ks)])
    ms = ((ms - ms.min()) / (ms.max() - ms.min()))

    results_filename = make_get_filepath(
        f'jackrabbit_results_grid/{ts_to_date(time())[:19]}')
    if settings['inverse']:
        results_filename += '_inverse'

    n_days = (agg_trades.timestamp.iloc[-1] -
              agg_trades.timestamp.iloc[0]) / 1000 / 60 / 60 / 24
    settings['n_days'] = n_days
    print('n_days', n_days)

    # conditions for result approval
    conditions = [
        lambda r: True,
    ]

    df = prep_df(agg_trades)

    while k < ks - 1:
        try:
            k += 1
            key = tuple([candidate[k_] for k_ in sorted(candidate)])
            if key in results:
                print('skipping', key)
                candidate = get_new_candidate(ranges, best)
                continue
            line = f'\n{k} m={ms[k]:.4f} best {tuple(best.values())}, '
            line += f'candidate {tuple(candidate.values())}'
            print(line)
            settings_ = {
                k_: candidate[k_] if k_ in candidate else settings[k_]
                for k_ in sorted(settings)
            }
            trades = backtest(df, settings_)
            if not trades:
                print('\nno trades')
                candidate = get_new_candidate(ranges, best)
                continue
            tdf = pd.DataFrame(trades).set_index('trade_id')
            n_closes = len(tdf[tdf.type == 'close'])
            pnl_sum = tdf.pnl.sum()
            loss_sum = tdf[tdf.pnl < 0.0].pnl.sum()
            abs_pos_sizes = tdf.pos_size.abs()
            if settings['inverse']:
                max_margin_cost = (abs_pos_sizes / tdf.pos_price /
                                   settings_['leverage']).max()
            else:
                max_margin_cost = (abs_pos_sizes * tdf.pos_price /
                                   settings_['leverage']).max()
            gain = (pnl_sum +
                    settings_['margin_limit']) / settings_['margin_limit']
            n_trades = len(tdf)
            result = {
                'n_closes': n_closes,
                'pnl_sum': pnl_sum,
                'loss_sum': loss_sum,
                'max_margin_cost': max_margin_cost,
                'gain': gain,
                'n_trades': n_trades
            }
            print('\n', result)
            results[key] = result

            if gain > best_gain and all([c(results[key]) for c in conditions]):
                best = candidate
                best_gain = gain
                print('\n\nnew best', best, '\n', gain, '\n')
                print(settings_)
                print(results[key], '\n\n')
            candidate = get_new_candidate(ranges, best, m=ms[k])
            pd.DataFrame(results).T.to_csv(results_filename + '.csv')
        except KeyboardInterrupt:
            return results
    return results