diff --git a/README.md b/README.md index f1fd3d5..a65eafd 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,23 @@ pip install -r requirements.txt pip install -e . ``` +## Use the library in your projects + +``` +from crypto_reflex.crypto_reflex_lib import crypto_reflex_lib # import the ligrary +cryptoReflex = crypto_reflex_lib +rebalance = cryptoReflex("binance", "{\"XRP\": 40.0, \"XLM\": 20.0, \"BTC\": 10.0, \"ETH\": 10.0, \"BNB\": 10.0, \"USDT\": 10.0}", "API_KEY", "API_SECRET", 0.2) +print(rebalance) # prints the output in JSON +``` +example of a return in JSON: + +``` +{"portfolio_value": 3.8687923544999996, "currency": "USDT", "cost": "0.002321"} +``` + ## Config -Create a config file in `config.ini` with the definition of your exchange and portfolio percentages, and theshold (percent) that rebalancing is needed. +THIS DOES NOT APPLY IF YOU ARE USING IT AS A LIBRARY +Create a config file in `config.ini` with the definition of your exchange and portfolio percentages, and threshold (percent) that rebalancing is needed. An example config file is included at `config.ini.example` but below is all you need: ``` @@ -46,7 +61,7 @@ By default it values the portfolio in USDT, this can be changed with `--valuebas To configure a proxy, simply create an environment variable named `PROXY_URL` -To get the the data returned as json simply use: `--json` +To get the data returned as JSON simply use: `--json` ## Running diff --git a/crypto_reflex/crypto_reflex_lib.py b/crypto_reflex/crypto_reflex_lib.py new file mode 100644 index 0000000..2f12e02 --- /dev/null +++ b/crypto_reflex/crypto_reflex_lib.py @@ -0,0 +1,124 @@ +import logging +import sys +import json + +from crypto_reflex.simple_balancer import SimpleBalancer +from crypto_reflex.ccxt_exchange import CCXTExchange +from crypto_reflex.executor import Executor +from crypto_reflex.portfolio import Portfolio + +logger = logging.getLogger(__name__) + + +def crypto_reflex_lib(exchange, target, api_key, api_secret, threshold, valuebase='USDT', trade=False, max_orders=5, force=False, mode='mid', j=True): + + + try: + + targets = json.loads(str(target)) + + except ValueError: + logger.error("Targets format invalid") + sys.exit(1) + + total_target = sum(targets.values()) + if total_target != 100: + logger.error("Total target needs to equal 100, it is {}" + .format(total_target)) + sys.exit(1) + + valuebase = valuebase + + exchange = CCXTExchange(exchange, + targets.keys(), + api_key, + api_secret) + if j == False: + print("Connected to exchange: {}".format(exchange.name)) + print() + + portfolio = Portfolio.make_portfolio(targets, exchange, threshold, valuebase) + if j == False: + print("Current Portfolio:") + for cur in portfolio.balances: + bal = portfolio.balances[cur] + pct = portfolio.balances_pct[cur] + tgt = targets[cur] + if j == False: + print(" {:<6s} {:<8.2f} ({:>5.2f} / {:>5.2f}%)" + .format(cur, bal, pct, tgt)) + + print() + print(" Total value: {:.16f} {}".format(portfolio.valuation_quote, + portfolio.quote_currency)) + balancer = SimpleBalancer() + executor = Executor(portfolio, exchange, balancer) + res = executor.run(force=force, + trade=trade, + max_orders=max_orders, + mode=mode) + if j == False: + print(" Balance RMS error: {:.2g} / {:.2g}".format( + res['initial_portfolio'].balance_rms_error, + threshold)) + + print(" Balance Max error: {:.2g} / {:.2g}".format( + res['initial_portfolio'].balance_max_error, + threshold)) + + print() + if not portfolio.needs_balancing and not force: + print("No balancing needed") + sys.exit(0) + if j == False: + print("Balancing needed{}:".format(" [FORCED]" if force else "")) + print() + print("Proposed Portfolio:") + portfolio = res['proposed_portfolio'] + + if not portfolio: + print("Could not calculate a better portfolio") + sys.exit(0) + + for cur in portfolio.balances: + bal = portfolio.balances[cur] + pct = portfolio.balances_pct[cur] + tgt = targets[cur] + if j == False: + print(" {:<6s} {:<8.16f} ({:>5.16f} / {:>5.16f}%)" + .format(cur, bal, pct, tgt)) + + print() + print(" Total value: {:.2f} {}".format(portfolio.valuation_quote, + portfolio.quote_currency)) + print(" Balance RMS error: {:.2g} / {:.2g}".format( + res['proposed_portfolio'].balance_rms_error, + threshold)) + + print(" Balance Max error: {:.2g} / {:.2g}".format( + res['proposed_portfolio'].balance_max_error, + threshold)) + + total_fee = '%s' % float('%.4g' % res['total_fee']) + if j == False: + print(" Total fees to re-balance: {} {}" + .format(total_fee, + portfolio.quote_currency)) + + print() + print("Orders:") + if trade: + for order in res['success']: + print(" Submitted: {}".format(order)) + + for order in res['errors']: + print(" Failed: {}".format(order)) + else: + for order in res['orders']: + print(" " + str(order)) + + + if j: + return json.dumps({"portfolio_value": portfolio.valuation_quote, "currency": portfolio.quote_currency, "cost": total_fee}) + + diff --git a/setup.py b/setup.py index 91b4be9..50401ae 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ readme = readme_file.read() setup(name='crypto_reflex', - version='1.0.0', + version='1.0.1', packages=['crypto_reflex'], entry_points={ 'console_scripts': [