Skip to content

Commit

Permalink
Use FRR on bitfinex as min_daily_rate (#554)
Browse files Browse the repository at this point in the history
* Return a dict of all currencies even if balance is 0

* Sleep and reduce requests per min if we get ERR_RATE_LIMIT

* Reduce request window to 1 sec

* Move the timers to millisecond resolution in the coach, MA changes times now when it catches 429

* Comments, logs, fix exception

* Don't change api request times unless using bitfinex

* Update polo coach to milliseconds

* Catch 429 at top level and more sensible api_req_period calc

* Use FRR for min_daily_rate

* Missing from last commit

* PEP-8

* Config and docs for frr as min

* Use config for frr and use configured min if higher

* Unrelated bug I found from ERR_RATE_LIMIT_fix

* Unrelated bug I found from ERR_RATE_LIMIT_fix

* Sync Bitfinex API requests completely

* Update test

* Update test

* Messed up the merge from bitfinex_sync_fix

* Messed up the merge from bitfinex_sync_fix

* Move timer change methods to base class and catch 429 at API level

* Add poloniex timer changes

* Make sure to re-raise the error, sleep in the MA module not the API.

* Converted a tab to spaces

* Added FRR Delta for Bitfinex

* Added FRR Delta for Bitfinex

* PEP-8

* Log when using FRR as min daily rate

* Allow config to be picked up from 'BOT' section rather than just coin_cfg

* Declare variables to allow global access

* This is why we should use classes!

* exchangeMax needs defined
  • Loading branch information
laxdog authored Jan 29, 2018
1 parent e6077cc commit fcd3fbb
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 9 deletions.
17 changes: 17 additions & 0 deletions default.cfg.example
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ hideCoins = True
#If set to 0 or commented: the bot will use the maxtolend or maxpercenttolend all the time. (0.0031-5)
#maxtolendrate = 0

#FRR as min, tells the bot whether or not to use the flash return rate (https://support.bitfinex.com/hc/en-us/articles/213919009-What-is-the-Flash-Return-Rate-)
#instead of mindailyrate. This only works on bitfinex.
#frrasmin = False

# The Flash Return Rate Delta (frrdelta) is a dynamic funding rate option that allows you to specify an offset from the Flash Return Rate. This only works on bitfinex and ffrasmin = TRUE
frrdelta = 0.0000

#Syntax: ["COIN:mindailyrate:maxactiveamount:maxtolend:maxpercenttolend:maxtolendrate",...]
#If maxactive amount is 0: stop lending this coin. in the future you'll be able to limit amount to be lent.
#If maxtolend is 0: check for maxpercenttolend.
Expand Down Expand Up @@ -143,6 +150,11 @@ hideCoins = True
#maxtolend = 0
#maxpercenttolend = 0
#maxtolendrate = 0
#gapmode = RawBTC
#gapbottom = 20
#gaptop = 400
#frrasmin = False
#frrdelta = 0.0000

#[CLAM]
#minloansize = 1
Expand All @@ -151,6 +163,11 @@ hideCoins = True
#maxtolend = 0
#maxpercenttolend = 0
#maxtolendrate = 0
#gapmode = raw
#gapbottom = 10
#gaptop = 20
#frrasmin = False
#frrdelta = 0.0000

[notifications]
notify_new_loans = False
Expand Down
17 changes: 16 additions & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ Min and Max Rates
- Allowed range: 0.0031 to 5 percent
- 2% is the default value offered by the exchange, but there is little reason not to set it higher if you feel optimistic.

- ``frrasmin`` tells the bot whether or not to use the `flash return rate <https://support.bitfinex.com/hc/en-us/articles/213919009-What-is-the-Flash-Return-Rate->`_ for ``mindailyrate``.
- Default value: False
- Allowed range: True or False
- This will only be used if the frr is above your ``mindailyrate``. So which ever is highest at the time of the loan will be used.
- This options only works on Bitfinex.

- ``frrdelta`` tells the bot whether or not to use the `flash return rate <https://support.bitfinex.com/hc/en-us/articles/115003284729-What-is-the-FRR-Delta->`
- Default value: 0.0000
- Allowed range: 0.0000 -/+ 7
- This will only be used if the frr is above your ``mindailyrate``. So which ever is highest at the time of the loan will be used.
- This options only works on Bitfinex.


Spreading your Lends
--------------------

Expand Down Expand Up @@ -216,7 +229,7 @@ Very few situations require you to change these settings.
- Allowed values: True or False. Commented defaults to True
- This hides your coins from appearing in walls.
- Allows you to catch a higher rate if it spikes past your ``mindailyrate``.
- Not necessarily recommended if used with ``analyseCurrencies`` with an aggressive ``lendingStyle``, as the bot may miss short-lived rate spikes.
- Not necessarily recommended if used with ``analyseCurrencies`` with an aggressive ``lendingStyle``, as the bot may miss short-lived rate spikes. This is not the case if using ``MACD`` with ``daily_min_method``. In that case it is recommended to set ``hideCoins`` to True.
- If you are using the ``analyseCurrencies`` option, you will likely see a lot of ``Not lending BTC due to rate below 0.9631%`` type messages in the logs. This is normal.

- ``endDate`` Bot will try to make sure all your loans are done by this date so you can withdraw or do whatever you need.
Expand Down Expand Up @@ -296,6 +309,8 @@ Configuration should look like this::
gapmode = raw
gapbottom = 10
gaptop = 20
frrasmin = true
frrdelta = 0.000000


Advanced logging and Web Display
Expand Down
15 changes: 13 additions & 2 deletions modules/Bitfinex.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,13 @@ def _post(self, command, payload=None, verify=True):
return self._request('post', payload['request'], signed_payload, verify)

@ExchangeApi.synchronized
def _get(self, command):
def _get(self, command, apiVersion=None):
# keep the request per minute limit
self.limit_request_rate()

request = '/{}/{}'.format(self.apiVersion, command)
if apiVersion is None:
apiVersion = self.apiVersion
request = '/{}/{}'.format(apiVersion, command)
return self._request('get', request)

def _get_symbols(self):
Expand Down Expand Up @@ -354,3 +356,12 @@ def return_lending_history(self, start, stop, limit=500):
})

return history

def get_frr(self, currency):
"""
Retrieves the flash return rate for the given currency
https://bitfinex.readme.io/v2/reference#rest-public-platform-status
"""
command = 'tickers?symbols=f' + currency
resp = self._get(command, 'v2')
return float(resp[0][1])
2 changes: 2 additions & 0 deletions modules/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ def get_coin_cfg():
coin_cfg[cur]['gapmode'] = get_gap_mode(cur, 'gapmode')
coin_cfg[cur]['gapbottom'] = Decimal(get(cur, 'gapbottom', False, 0))
coin_cfg[cur]['gaptop'] = Decimal(get(cur, 'gaptop', False, coin_cfg[cur]['gapbottom']))
coin_cfg[cur]['frrasmin'] = getboolean(cur, 'frrasmin', getboolean('BOT', 'frrasmin'))
coin_cfg[cur]['frrdelta'] = Decimal(get(cur, 'frrdelta', 0.0000))

except Exception as ex:
ex.message = ex.message if ex.message else str(ex)
Expand Down
43 changes: 37 additions & 6 deletions modules/Lending.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
gap_mode_default = ""
scheduler = None
exchange = None
frrasmin = False
frrdelta = 0.0

# limit of orders to request
loanOrdersRequestLimit = {}
Expand All @@ -58,7 +60,7 @@ def init(cfg, api1, log1, data, maxtolend, dry_run1, analysis, notify_conf1):
global sleep_time, sleep_time_active, sleep_time_inactive, min_daily_rate, max_daily_rate, spread_lend, \
gap_bottom_default, gap_top_default, xday_threshold, xday_spread, xdays, min_loan_size, end_date, coin_cfg, \
min_loan_sizes, dry_run, transferable_currencies, keep_stuck_orders, hide_coins, scheduler, gap_mode_default, \
exchange, analysis_method, currencies_to_analyse, all_currencies
exchange, analysis_method, currencies_to_analyse, all_currencies, frrasmin, frrdelta

exchange = Config.get_exchange()

Expand All @@ -85,6 +87,8 @@ def init(cfg, api1, log1, data, maxtolend, dry_run1, analysis, notify_conf1):
currencies_to_analyse = Config.get_currencies_list('analyseCurrencies', 'MarketAnalysis')
keep_stuck_orders = Config.getboolean('BOT', "keepstuckorders", True)
hide_coins = Config.getboolean('BOT', 'hideCoins', True)
frrasmin = Config.getboolean('BOT', 'frrasmin', False)
frrdelta = Decimal(Config.get('BOT', 'frrdelta', 0.0000))
analysis_method = Config.get('Daily_min', 'method', 'percentile')
if analysis_method not in ['percentile', 'MACD']:
raise ValueError("analysis_method: \"{0}\" is not valid, must be percentile or MACD".format(analysis_method))
Expand Down Expand Up @@ -131,13 +135,14 @@ def notify_new_loans(sleep_time):
if loans_provided:
# function to return a set of ids from the api result
# get_id_set = lambda loans: set([x['id'] for x in loans])
def get_id_set(loans): return set([x['id'] for x in loans])
def get_id_set(loans):
return set([x['id'] for x in loans])
loans_amount = {}
loans_info = {}
for loan_id in get_id_set(new_provided) - get_id_set(loans_provided):
loan = [x for x in new_provided if x['id'] == loan_id][0]
# combine loans with the same rate
k = 'c'+loan['currency']+'r'+loan['rate']+'d'+str(loan['duration'])
k = 'c' + loan['currency'] + 'r' + loan['rate'] + 'd' + str(loan['duration'])
loans_amount[k] = float(loan['amount']) + (loans_amount[k] if k in loans_amount else 0)
loans_info[k] = loan
# send notifications with the grouped info
Expand Down Expand Up @@ -250,21 +255,47 @@ def lend_all():
set_sleep_time(usable_currencies)


def get_frr_or_min_daily_rate(cur):
"""
Checks the Flash Return Rate of cur against the min daily rate and returns the better of the two. If not using
bitfinex then it will always return the min daily rate for the currency.
:param cur: The currency which to check
:return: The better of the two rates (FRR and min daily rate)
"""
if cur in coin_cfg:
min_daily_rate = Decimal(coin_cfg[cur]['minrate'])
frrasmin = coin_cfg[cur]['frrasmin']
frrdelta = Decimal(coin_cfg[cur]['frrdelta']) / 100
else:
min_daily_rate = Decimal(Config.get("BOT", "mindailyrate", None, 0.003, 5)) / 100
frrasmin = Config.getboolean('BOT', 'frrasmin', False)
frrdelta = Decimal(Config.get('BOT', 'frrdelta', 0.0000))

if exchange == 'BITFINEX' and frrasmin:
frr_rate = Decimal(api.get_frr(cur)) + frrdelta
if frr_rate > min_daily_rate:
log.log("Using FRR as mindailyrate {0}% for {1}".format(frr_rate * 100, cur))
return frr_rate

return min_daily_rate


def get_min_daily_rate(cur):
cur_min_daily_rate = min_daily_rate
cur_min_daily_rate = get_frr_or_min_daily_rate(cur)
if cur in coin_cfg:
if coin_cfg[cur]['maxactive'] == 0:
if cur not in max_active_alerted: # Only alert once per coin.
max_active_alerted[cur] = True
log.log('maxactive amount for ' + cur + ' set to 0, won\'t lend.')
return False
cur_min_daily_rate = Decimal(coin_cfg[cur]['minrate'])
if cur not in coin_cfg_alerted: # Only alert once per coin.
coin_cfg_alerted[cur] = True
log.log('Using custom mindailyrate ' + str(coin_cfg[cur]['minrate'] * 100) + '% for ' + cur)
log.log('Using custom mindailyrate ' + str(cur_min_daily_rate * 100) + '% for ' + cur)
if Analysis and cur in currencies_to_analyse:
recommended_min = Analysis.get_rate_suggestion(cur, method=analysis_method)
if cur_min_daily_rate < recommended_min:
log.log("Using {0} as mindailyrate {1}% for {2}".format(analysis_method, recommended_min * 100, cur))
cur_min_daily_rate = recommended_min
return Decimal(cur_min_daily_rate)

Expand Down

0 comments on commit fcd3fbb

Please sign in to comment.