Last active
October 30, 2023 09:28
-
-
Save Asoul/15ffdfb18e135966e36f2e1834345986 to your computer and use it in GitHub Desktop.
Bitfinex lending bot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import base64 | |
import json | |
import hmac | |
import hashlib | |
import requests | |
URL = 'https://api.bitfinex.com' | |
API_VERSION = '/v1' | |
API_KEY = '' | |
API_SECRET = '' | |
def _post(endpoint, payload=None): | |
payload = payload or {} | |
payload['request'] = API_VERSION + endpoint | |
payload['nonce'] = str(int(time.time() * 1000)) | |
base64_payload = base64.b64encode(json.dumps(payload).encode()) | |
signature = hmac.new(API_SECRET.encode(), base64_payload, digestmod=hashlib.sha384)\ | |
.hexdigest() | |
signed_payload = { | |
'X-BFX-APIKEY': API_KEY, | |
'X-BFX-PAYLOAD': base64_payload, | |
'X-BFX-SIGNATURE': signature | |
} | |
response = requests.post(URL + API_VERSION + endpoint, headers=signed_payload, timeout=10) | |
if not response.ok: | |
print(f'post {endpoint} failed') | |
print(response.content) | |
raise ValueError(response) | |
return response.json() | |
def get_lend_rate(currency): | |
# Get the past 2 hours average | |
data = requests.get(f'https://api-pub.bitfinex.com/v2/candles/trade:15m:f{currency.upper()}:p15/hist?limit=8').json() | |
ma8_ratio = sum(d[2] for d in data) / 8 | |
highest_ratio = max(d[3] for d in data) | |
# Use the average of moving average and highest | |
ratio = (ma8_ratio + highest_ratio) / 2 * 100 | |
ratio = max(ratio, 0.041) | |
# v1 api use yearly raio, v2 use daily ratio | |
return ratio * 365 | |
def create_offer(currency, amount, rate, period): | |
print(f'Lend {currency.upper()} {round(amount)}, {rate:.5}%, {period} days') | |
return _post('/offer/new', { | |
'currency': currency.upper(), | |
'amount': str(int(amount)), | |
'rate': str(rate), | |
'period': period, | |
'direction': 'lend' | |
}) | |
def cancel_offer(offer_id): | |
print(f'Cancel offer {offer_id}') | |
return _post('/offer/cancel', { | |
'offer_id': offer_id | |
}) | |
def get_open_offers(): | |
return _post('/offers') | |
def get_period_by_rate(rate): | |
if rate < 15: | |
return 5 | |
elif rate < 20: | |
return 10 | |
elif rate > 30: | |
return 30 | |
return 20 | |
def main(): | |
offers = get_open_offers() | |
for offer in offers: | |
cancel_offer(offer['id']) | |
currency_pairs = _post('/balances') | |
for currency_pair in currency_pairs: | |
if currency_pair['type'] != 'deposit': | |
continue | |
if currency_pair['currency'] not in ['usd', 'ust']: | |
continue | |
currency = currency_pair['currency'] | |
amount = float(currency_pair['available']) | |
if amount <= 50: | |
continue | |
rate = get_lend_rate(currency) | |
period = get_period_by_rate(rate) | |
create_offer(currency, amount, rate, period) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*/15 * * * * /usr/bin/python3 /opt/apps/run.py |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment