I have created a simple tool that takes in a dictionary of cryptocurrencies and finds the ones with the highest % differences between exchanges. I would be grateful if someone could help me optimize this code and perhaps make it less complicated. The structure of the code is:
for coin in data: for market in coin.markets() if conditions_are_met: if is_highest_price: high_price = new_high_price if is_lowest_price: low_price = new_low_price coin_differences = append([coin.name, high_price-low_price]) display_top_10(coin_differences)
This is the actual code:
#!/usr/bin/env python3
import decimal
import argparse
from operator import itemgetter
try:
import pymarketcap
except Exception as e:
print('Make sure to install {0} (python3 -m pip {0}.'.format(str(e).split("'")[1]))
exit()
# arguments
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--minimum_vol', type=float, help='Minimum Percent volume per exchange to have to count', default=1)
parser.add_argument('-p', '--pairs', nargs='*', default=[], help='Pairs the coins can be arbitraged with - default=all')
parser.add_argument('-c', '--coins_shown', type=int, default=10, help='Number of coins to show')
parser.add_argument('-e', '--exchanges', nargs='*', help='Acceptable Exchanges - default=all', default=[])
parser.add_argument('-s', '--simple', help='Toggle off errors and settings', default=False, action="store_true")
parser.add_argument('-t', '--top', type=int, help='Set the number of coins to run with', default=100)
args = parser.parse_args()
# setup
cmc = pymarketcap.Pymarketcap()
info = []
count = 1
lowercase_exchanges = [x.lower() for x in args.exchanges]
all_exchanges = not bool(args.exchanges)
all_trading_pairs = not bool(args.pairs)
coin_format = '{: <25} {: >6}% {: >10} {: >15} {: <10} {: <10} {: <15} {: <5}'
if not args.simple:
print('CURRENT SETTINGS',
'* MINIMUM_PERCENT_VOL: {}'.format(args.minimum_vol),
'* TRADING_PAIRS: {}'.format(args.pairs),
'* COINS_SHOWN: {}'.format(args.coins_shown),
'* EXCHANGES: {}'.format(lowercase_exchanges),
'* ALL_TRADING_PAIRS: {}'.format(all_trading_pairs),
'* ALL_EXCHANGES: {}'.format(all_exchanges),
'* TOP: {}'.format(args.top),
sep='\n')
# retrieve coin data
coin_data = cmc.ticker(limit=args.top)['data']
for id_, coin in coin_data.items():
try:
markets = cmc.markets(coin["id"])
except Exception as e:
markets = cmc.markets(coin["symbol"])
best_price = 0
best_exchange = ''
best_pair = ''
worst_price = 999999 # TODO is this value high enough? one day some cryptocurrencies will be worth several millions... i hope :)
worst_exchange = ''
worst_pair = ''
has_markets = False
for market in markets["markets"]:
trades_into = market["pair"].replace(coin["symbol"],"").replace("-","").replace("/","")
if (market['percent_volume'] >= args.minimum_vol and
market['updated'] and
(trades_into in args.pairs or all_trading_pairs) and
(market['source'].lower() in lowercase_exchanges or all_exchanges)
):
has_markets = True
if market['price'] >= best_price:
best_price = market['price']
best_exchange = market['source']
best_pair = trades_into
if market['price'] <= worst_price:
worst_price = market['price']
worst_exchange = market['source']
worst_pair = trades_into
if has_markets:
info.append([coin['name'],
round((best_price/worst_price-1)*100,2),
worst_price,
worst_exchange,
worst_pair,
best_price,
best_exchange,
best_pair
])
elif not args.simple:
print(coin['name'],'had no markets that fit the criteria.')
print('[{}/{}]'.format(count, args.top),end='\r')
count += 1
# show data
info = sorted(info, key=itemgetter(1), reverse=True)
print(coin_format.format("COIN","CHANGE","BUY PRICE","BUY AT","BUY WITH","SELL PRICE","SELL AT","SELL WITH"))
for coin in info[0:args.coins_shown]:
print(coin_format.format(*coin))
-
\$\begingroup\$ Welcome to Code Review! I hope you get some good answers. \$\endgroup\$Phrancis– Phrancis2018年05月29日 18:57:56 +00:00Commented May 29, 2018 at 18:57
1 Answer 1
Some random advice:
Consider using ArgumentDefaultsHelpFormatter
. It's a nice thing to use when you have so many defaults set.
I would lose the try/import/except. It's just as good to let the default failure take place. You can specify pip requirements in requirements.txt
.
Group up your code into functions, even if they're only called once. There are many reasons for this - stack traces are improved, code folding is actually useful, and code legibility goes up.
Your explicit calls to bool()
are no-ops. Python already treats everything as truthy/falsy.
Indexing [0 :x]
is the same as indexing [:x]
.
Explore related questions
See similar questions with these tags.