|
| 1 | +# !/usr/bin/env python |
| 2 | +# coding: utf-8 |
| 3 | +import logging |
| 4 | +import random |
| 5 | +from decimal import Decimal as D, ROUND_UP, getcontext |
| 6 | + |
| 7 | +from gate_api import ApiClient, Configuration, Loan, MarginApi, Order, RepayRequest, SpotApi, Transfer, WalletApi |
| 8 | +from gate_api.exceptions import GateApiException |
| 9 | + |
| 10 | +from config import RunConfig |
| 11 | + |
| 12 | +logger = logging.getLogger(__name__) |
| 13 | + |
| 14 | + |
| 15 | +def margin_demo(run_config): |
| 16 | + # type: (RunConfig) -> None |
| 17 | + currency_pair = 'BTC_USDT' |
| 18 | + currency = currency_pair.split("_")[1] |
| 19 | + |
| 20 | + # Initialize API client |
| 21 | + # Setting host is optional. It defaults to https://api.gateio.ws/api/v4 |
| 22 | + config = Configuration(key=run_config.api_key, secret=run_config.api_secret, host=run_config.host_used) |
| 23 | + spot_api = SpotApi(ApiClient(config)) |
| 24 | + margin_api = MarginApi(ApiClient(config)) |
| 25 | + wallet_api = WalletApi(ApiClient(config)) |
| 26 | + |
| 27 | + # retrieve currency pair last price |
| 28 | + tickers = spot_api.list_tickers(currency_pair=currency_pair) |
| 29 | + assert len(tickers) == 1 |
| 30 | + last_price = tickers[0].last |
| 31 | + logger.info("currency pair %s last price %s", currency_pair, last_price) |
| 32 | + |
| 33 | + pairs = margin_api.list_margin_currency_pairs() |
| 34 | + pair = next(p for p in pairs if p.id == currency_pair) |
| 35 | + loan_amount = D("0") if not pair.min_quote_amount else D(pair.min_quote_amount) |
| 36 | + |
| 37 | + if pair.min_base_amount: |
| 38 | + min_loan_amount = D(pair.min_base_amount) * D(last_price) |
| 39 | + if loan_amount < min_loan_amount: |
| 40 | + loan_amount = min_loan_amount |
| 41 | + logger.info("minimum loan amount in currency pair %s: %s %s", currency_pair, str(loan_amount), currency) |
| 42 | + |
| 43 | + getcontext().prec = 8 |
| 44 | + getcontext().rounding = ROUND_UP |
| 45 | + |
| 46 | + # example to lend |
| 47 | + funding_accounts = margin_api.list_funding_accounts(currency=currency) |
| 48 | + lend_amount = loan_amount + D(random.random()) |
| 49 | + if len(funding_accounts) == 1 and D(funding_accounts[0].available) >= lend_amount: |
| 50 | + lending_loan = Loan(amount=str(lend_amount), auto_renew=False, days=10, currency=currency, rate="0.002", |
| 51 | + side='lend') |
| 52 | + created_loan = margin_api.create_loan(lending_loan) |
| 53 | + logger.info("place a lending loan %s with currency %s, rate %s, amount %s", created_loan.id, |
| 54 | + created_loan.currency, created_loan.rate, created_loan.amount) |
| 55 | + loan_result = margin_api.get_loan(created_loan.id, 'lend') |
| 56 | + if loan_result.status == 'loaned': |
| 57 | + records = margin_api.list_loan_records(loan_result.id) |
| 58 | + for r in records: |
| 59 | + logger.info("loan %s is borrowed with record id %s, amount %s, status: %s", r.loan_id, r.id, r.amount, |
| 60 | + r.status) |
| 61 | + else: |
| 62 | + margin_api.cancel_loan(created_loan.id, currency) |
| 63 | + |
| 64 | + assert pair.leverage |
| 65 | + margin = loan_amount / (pair.leverage - 1) |
| 66 | + accounts = margin_api.list_margin_accounts(currency_pair=currency_pair) |
| 67 | + assert len(accounts) == 1 |
| 68 | + available = D(accounts[0].quote.available) |
| 69 | + logger.info("available margin balance of currency %s in currency pair %s: %s", currency, currency_pair, |
| 70 | + str(available)) |
| 71 | + if margin > available: |
| 72 | + transfer = Transfer(currency_pair=currency_pair, currency=currency, amount=str(margin - available), |
| 73 | + _from='spot', to='margin') |
| 74 | + wallet_api.transfer(transfer) |
| 75 | + logger.info("transferred %s %s to margin account", transfer.amount, transfer.currency) |
| 76 | + |
| 77 | + # borrow with minimum rate |
| 78 | + borrow_amount = loan_amount + D(random.random()) |
| 79 | + min_rate_item = min( |
| 80 | + filter(lambda x: x.rate and D(x.amount) > borrow_amount, margin_api.list_funding_book(currency)), |
| 81 | + key=lambda x: D(x.rate) |
| 82 | + ) |
| 83 | + loan = Loan(side='borrow', currency=currency, rate=min_rate_item.rate, amount=str(borrow_amount), |
| 84 | + days=min_rate_item.days, currency_pair=currency_pair) |
| 85 | + borrowed = margin_api.create_loan(loan) |
| 86 | + logger.info("borrowed %s %s in currency pair %s with rate %s, id %s", borrowed.amount, borrowed.currency, |
| 87 | + borrowed.currency_pair, borrowed.rate, borrowed.id) |
| 88 | + assert borrowed.status == 'loaned' |
| 89 | + |
| 90 | + # create margin order |
| 91 | + order_amount = spot_api.get_currency_pair(currency_pair).min_quote_amount |
| 92 | + order = Order(account='margin', currency_pair=currency_pair, price=last_price, amount=order_amount or "1", |
| 93 | + side='sell') |
| 94 | + try: |
| 95 | + created_order = spot_api.create_order(order) |
| 96 | + logger.info("margin order created with id %s, status %s", created_order.id, created_order.status) |
| 97 | + except GateApiException as ex: |
| 98 | + logger.error("failed to create margin order: %s", ex) |
| 99 | + |
| 100 | + repay_request = RepayRequest(mode='all', currency=currency, currency_pair=currency_pair) |
| 101 | + margin_api.repay_loan(borrowed.id, repay_request) |
| 102 | + for r in margin_api.list_loan_repayments(borrowed.id): |
| 103 | + logger.info("loan %s repaid %s with interest %s", borrowed.id, r.principal, r.interest) |
0 commit comments