diff --git a/.travis.yml b/.travis.yml index ac271b3..45a7061 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,18 @@ addons: python: - "2.7" + - "3.6" + +matrix: + allow_failures: + - python: "3.6" install: - pip install . +before_script: + - pip install flake8 + # TODO: Fix the flake8 tests and the remove the --exit-zero + - flake8 . --count --exit-zero --select=E9,F63,F7,F82 --show-source --statistics + script: gryphon-runtests diff --git a/gryphon/dashboards/handlers/block_times.py b/gryphon/dashboards/handlers/block_times.py index 61e7784..85d6b9a 100755 --- a/gryphon/dashboards/handlers/block_times.py +++ b/gryphon/dashboards/handlers/block_times.py @@ -1,7 +1,8 @@ -from admin_base import AdminBaseHandler +from __future__ import absolute_import +from .admin_base import AdminBaseHandler import tornado.web -from mixins.start_and_end_time import StartAndEndTimeMixin +from .mixins.start_and_end_time import StartAndEndTimeMixin import util.tick_times as tick_times diff --git a/gryphon/dashboards/handlers/home.py b/gryphon/dashboards/handlers/home.py index 06f2263..b30b8c5 100755 --- a/gryphon/dashboards/handlers/home.py +++ b/gryphon/dashboards/handlers/home.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import tornado.web -from admin_base import AdminBaseHandler +from .admin_base import AdminBaseHandler class HomeHandler(AdminBaseHandler): diff --git a/gryphon/dashboards/handlers/ledger.py b/gryphon/dashboards/handlers/ledger.py index 59cfe5c..0d3edf6 100755 --- a/gryphon/dashboards/handlers/ledger.py +++ b/gryphon/dashboards/handlers/ledger.py @@ -142,7 +142,7 @@ def get_exchange_for_address(self, address): """ if address and address in self.address_map: - return address_map[address] + return self.address_map[address] else: return 'External transfer' @@ -261,7 +261,7 @@ def table_entries_from_transaction(self, transaction): entry['date'] = date entry['details'] = ''.join([ '%s:%s ' % (k, v) - for k, v in transaction.transaction_details.iteritems() + for k, v in transaction.transaction_details.items() if k in ['external_transaction_id', 'notes'] and v not in ['xxx'] ]) diff --git a/gryphon/dashboards/handlers/status.py b/gryphon/dashboards/handlers/status.py index 9a620af..90b175a 100755 --- a/gryphon/dashboards/handlers/status.py +++ b/gryphon/dashboards/handlers/status.py @@ -140,7 +140,7 @@ def get_system_balances(self, exchanges): system_balance += e.exchange_account_db_object(self.trading_db).balance total_fiat = sum([ - balance.to("USD") for currency, balance in system_balance.iteritems() + balance.to("USD") for currency, balance in system_balance.items() if currency not in Money.CRYPTO_CURRENCIES ]) diff --git a/gryphon/dashboards/handlers/tick_times.py b/gryphon/dashboards/handlers/tick_times.py index 3a72039..4347a6a 100755 --- a/gryphon/dashboards/handlers/tick_times.py +++ b/gryphon/dashboards/handlers/tick_times.py @@ -1,7 +1,8 @@ -from admin_base import AdminBaseHandler +from __future__ import absolute_import +from .admin_base import AdminBaseHandler import tornado.web -from mixins.start_and_end_time import StartAndEndTimeMixin +from .mixins.start_and_end_time import StartAndEndTimeMixin from tinkerpy.exchange.exchange_factory import all_exchanges import util.tick_times as tick_times diff --git a/gryphon/dashboards/models/base.py b/gryphon/dashboards/models/base.py index 3d30076..ac67fc5 100755 --- a/gryphon/dashboards/models/base.py +++ b/gryphon/dashboards/models/base.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- +from six import text_type from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() metadata = Base.metadata def unicode_string(self): - return unicode(self).encode('utf-8') + return text_type(self).encode('utf-8') -Base.__str__ == unicode_string +Base.__str__ == unicode_string # How to migrate a database diff --git a/gryphon/dashboards/settings.py b/gryphon/dashboards/settings.py index bfe88d2..6f33fd8 100755 --- a/gryphon/dashboards/settings.py +++ b/gryphon/dashboards/settings.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import logging import tornado import tornado.template @@ -6,7 +7,7 @@ from os.path import dirname, abspath from tornado.options import define, options from gryphon.lib.logperf import log_request_perf -import uimodules +from . import uimodules # Make filepaths relative to settings. path = lambda root,*a: os.path.join(root, *a) diff --git a/gryphon/dashboards/util/balances.py b/gryphon/dashboards/util/balances.py index 38fc9e9..7a67279 100755 --- a/gryphon/dashboards/util/balances.py +++ b/gryphon/dashboards/util/balances.py @@ -12,7 +12,7 @@ def get_balance_time_series_from_audits(audits): fiat_balances = [] btc_balances = [] - + for audit in audits: timestamp = int(Delorean(audit.time_created, "UTC").epoch) * 1000 @@ -34,7 +34,7 @@ def get_balance_time_series_from_audits(audits): continue # convert to Money objects - for currency, balance_str in balance_data.iteritems(): + for currency, balance_str in balance_data.items(): balance_data[currency] = Money.loads(balance_str) balance = Balance(balance_data) @@ -103,7 +103,7 @@ def get_drift_from_audits(audits): if 'drift' in audit.data: data = json.loads(audit.data) - for currency, str_amount in data['drift'].iteritems(): + for currency, str_amount in data['drift'].items(): drift_by_currency += Money.loads(str_amount) return drift_by_currency diff --git a/gryphon/data_service/auditors/orderbook_auditor.py b/gryphon/data_service/auditors/orderbook_auditor.py index 2852622..9737494 100755 --- a/gryphon/data_service/auditors/orderbook_auditor.py +++ b/gryphon/data_service/auditors/orderbook_auditor.py @@ -242,7 +242,7 @@ def audit_orderbook(self, orderbook, orderbook_timestamp): if not our_orderbooks: log.msg('No orderbooks to audit against') - for key, value in fundamental_values.iteritems(): + for key, value in fundamental_values.items(): log.msg( '------ Fundamental Value Closeness:%.6f, DBfv:%s, HTTPfv:%s' % ( key, @@ -250,7 +250,7 @@ def audit_orderbook(self, orderbook, orderbook_timestamp): value['http_fundamental_value'] )) - for key, value in change_dict.iteritems(): + for key, value in change_dict.items(): log.msg('------ Change Count: %s' % key) log.msg( diff --git a/gryphon/data_service/pollers/orderbook/kraken_cad_orderbook_poller.py b/gryphon/data_service/pollers/orderbook/kraken_cad_orderbook_poller.py index e91067c..28573e2 100755 --- a/gryphon/data_service/pollers/orderbook/kraken_cad_orderbook_poller.py +++ b/gryphon/data_service/pollers/orderbook/kraken_cad_orderbook_poller.py @@ -1,4 +1,5 @@ -from kraken_orderbook_poller import KrakenOrderbook +from __future__ import absolute_import +from .kraken_orderbook_poller import KrakenOrderbook class KrakenCADOrderbook(KrakenOrderbook): diff --git a/gryphon/data_service/pollers/orderbook/kraken_usd_orderbook_poller.py b/gryphon/data_service/pollers/orderbook/kraken_usd_orderbook_poller.py index 191b145..90efd67 100755 --- a/gryphon/data_service/pollers/orderbook/kraken_usd_orderbook_poller.py +++ b/gryphon/data_service/pollers/orderbook/kraken_usd_orderbook_poller.py @@ -1,4 +1,5 @@ -from kraken_orderbook_poller import KrakenOrderbook +from __future__ import absolute_import +from .kraken_orderbook_poller import KrakenOrderbook class KrakenUSDOrderbook(KrakenOrderbook): diff --git a/gryphon/data_service/pollers/orderbook/websocket/bitfinex_orderbook_websocket.py b/gryphon/data_service/pollers/orderbook/websocket/bitfinex_orderbook_websocket.py index 736b8f2..4525c61 100755 --- a/gryphon/data_service/pollers/orderbook/websocket/bitfinex_orderbook_websocket.py +++ b/gryphon/data_service/pollers/orderbook/websocket/bitfinex_orderbook_websocket.py @@ -130,11 +130,11 @@ def get_orderbook_to_publish(self): bids = [] asks = [] - for price, volume in sorted(self.bids_dict.iteritems(), reverse=True): + for price, volume in sorted(self.bids_dict.items(), reverse=True): if volume > 0: bids.append([str(price), str(volume), '']) - for price, volume in sorted(self.asks_dict.iteritems()): + for price, volume in sorted(self.asks_dict.items()): if volume > 0: asks.append([str(price), str(volume), '']) diff --git a/gryphon/data_service/pollers/orderbook/websocket/bitstamp_orderbook_websocket.py b/gryphon/data_service/pollers/orderbook/websocket/bitstamp_orderbook_websocket.py index 8935921..0ea61d6 100755 --- a/gryphon/data_service/pollers/orderbook/websocket/bitstamp_orderbook_websocket.py +++ b/gryphon/data_service/pollers/orderbook/websocket/bitstamp_orderbook_websocket.py @@ -211,26 +211,26 @@ def apply_change_to_orderbook(self, change): # Remove the 0 volumes from the orderbook. self.orderbook['bids'].update(bids_changes) - for k, v in self.orderbook['bids'].iteritems(): + for k, v in self.orderbook['bids'].items(): if v == "0": self.orderbook['bids'].pop(k) # Re-sort the bids. self.orderbook['bids'] = OrderedDict(sorted( - self.orderbook['bids'].iteritems(), - key=lambda (k, v): float(k), + self.orderbook['bids'].items(), + key=lambda k_v1: float(k_v1[0]), reverse=True, )) self.orderbook['asks'].update(asks_changes) - for k, v in self.orderbook['asks'].iteritems(): + for k, v in self.orderbook['asks'].items(): if v == "0": self.orderbook['asks'].pop(k) # Re-sort the asks. self.orderbook['asks'] = OrderedDict( - sorted(self.orderbook['asks'].iteritems(), key=lambda (k, v): float(k)), + sorted(self.orderbook['asks'].items(), key=lambda k_v: float(k_v[0])), ) def parse_orders(self, orders): @@ -247,7 +247,7 @@ def get_orderbook_to_publish(self): price_key_orderbook = self.orderbook return { - 'bids': [[k, v, ''] for k, v in price_key_orderbook['bids'].iteritems()], - 'asks': [[k, v, ''] for k, v in price_key_orderbook['asks'].iteritems()], + 'bids': [[k, v, ''] for k, v in price_key_orderbook['bids'].items()], + 'asks': [[k, v, ''] for k, v in price_key_orderbook['asks'].items()], } diff --git a/gryphon/data_service/pollers/orderbook/websocket/coinbase_orderbook_websocket.py b/gryphon/data_service/pollers/orderbook/websocket/coinbase_orderbook_websocket.py index 18e3fe5..aefb1cd 100755 --- a/gryphon/data_service/pollers/orderbook/websocket/coinbase_orderbook_websocket.py +++ b/gryphon/data_service/pollers/orderbook/websocket/coinbase_orderbook_websocket.py @@ -309,13 +309,13 @@ def get_orderbook_to_publish(self): sorted_bid_keys = sorted( fancy_orderbook['bids'].keys(), - key=lambda (k): float(k), + key=lambda k: float(k), reverse=True, ) sorted_ask_keys = sorted( fancy_orderbook['asks'].keys(), - key=lambda (k): float(k), + key=lambda k: float(k), ) bids = [[k, str(fancy_orderbook['bids'][k]), ''] for k in sorted_bid_keys] diff --git a/gryphon/data_service/pollers/trades/trades_poller.py b/gryphon/data_service/pollers/trades/trades_poller.py index 0a802de..38d7462 100755 --- a/gryphon/data_service/pollers/trades/trades_poller.py +++ b/gryphon/data_service/pollers/trades/trades_poller.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import json +from six import text_type import termcolor as tc from twisted.internet import defer from twisted.internet.task import LoopingCall @@ -50,9 +51,9 @@ def parse_response(self, resp_obj): for trade in trades: if trade['trade_id'] > self.most_recent_trade_id: trade['price_currency'] = trade['price'].currency - trade['price'] = unicode(trade['price'].amount) + trade['price'] = text_type(trade['price'].amount) trade['volume_currency'] = trade['volume'].currency - trade['volume'] = unicode(trade['volume'].amount) + trade['volume'] = text_type(trade['volume'].amount) trade['timestamp'] = int(trade['timestamp']) trade_string = json.dumps(trade, ensure_ascii=False) self.producer.publish_message(trade_string) diff --git a/gryphon/data_service/scripts/autobahn-tester.py b/gryphon/data_service/scripts/autobahn-tester.py index 9680871..af6dcf6 100755 --- a/gryphon/data_service/scripts/autobahn-tester.py +++ b/gryphon/data_service/scripts/autobahn-tester.py @@ -1,3 +1,4 @@ +from __future__ import print_function ############################################################################### ## ## Copyright (C) 2011-2013 Tavendo GmbH diff --git a/gryphon/data_service/scripts/benchmark.py b/gryphon/data_service/scripts/benchmark.py index a347bb7..d7f2cd5 100755 --- a/gryphon/data_service/scripts/benchmark.py +++ b/gryphon/data_service/scripts/benchmark.py @@ -1,3 +1,4 @@ +from __future__ import print_function # Simple test script for benchmarking regular python logging vs twisted's logging. import logging @@ -25,7 +26,7 @@ def tx_log(): def stop(): - print "Log Counter: %s" % log_counter + print("Log Counter: %s" % log_counter) reactor.stop() diff --git a/gryphon/data_service/scripts/historical_trade_collector.py b/gryphon/data_service/scripts/historical_trade_collector.py index 8c93789..5bf99c5 100755 --- a/gryphon/data_service/scripts/historical_trade_collector.py +++ b/gryphon/data_service/scripts/historical_trade_collector.py @@ -1,3 +1,4 @@ +from __future__ import print_function import csv from datetime import timedelta import gzip @@ -161,7 +162,7 @@ def get_our_recorded_ticker_volume_for_period(exchange, start_date, end_date): def audit_ticker_volume_individual_days(exchange_list, start_date=test_start_date, end_date=test_end_date): d = start_date while d < test_end_date: - print '\n\nAuditing: %s' % d + print('\n\nAuditing: %s' % d) day_after = d + timedelta(days=1) audit_all_ticker_volume(exchange_list, d, day_after) d = day_after @@ -191,12 +192,12 @@ def audit_ticker_volume(exchange, start_date, end_date): end_date, ) - print '%s Our Volume:%s Ticker Volume:%s, Accuracy: %s' % ( + print('%s Our Volume:%s Ticker Volume:%s, Accuracy: %s' % ( exchange, our_volume, ticker_volume, our_volume / ticker_volume, - ) + )) def audit_bw_volume(exchange, start_date, end_date): @@ -204,7 +205,7 @@ def audit_bw_volume(exchange, start_date, end_date): bw_volume = bw_exchange.volume_in_period(start_date, end_date) our_volume = get_our_recorded_exchange_trade_volume_for_period(exchange, start_date, end_date) - print '%s Our Volume:%s BW Volume:%s, Accuracy: %s' % (exchange, our_volume, bw_volume, our_volume / bw_volume) + print('%s Our Volume:%s BW Volume:%s, Accuracy: %s' % (exchange, our_volume, bw_volume, our_volume / bw_volume)) def compare_all_exchanges(): @@ -222,15 +223,15 @@ def compare_ours_to_history(our_exchange_id, exchange, price_currency, volume_cu start = parse('2015-11-27 0:0:0').datetime.replace(tzinfo=None) end = parse('2015-11-27 11:59:59').datetime.replace(tzinfo=None) - print our_exchange_id.upper() + print(our_exchange_id.upper()) hist_in_range = [t for t in hist_trades if t[0] >= start and t[0] <= end] ours_in_range = [t for t in our_trades if t[0] >= start and t[0] <= end] for t in hist_in_range: if t not in ours_in_range: - print 'Hist Trade not in ours: %s' % t + print('Hist Trade not in ours: %s' % t) for t in ours_in_range: if t not in hist_in_range: - print'Our trade not in history: %s' % t - print'\n\n\n\n\n' + print('Our trade not in history: %s' % t) + print('\n\n\n\n\n') diff --git a/gryphon/execution/bots/overwatch.py b/gryphon/execution/bots/overwatch.py index ab6912a..6d00863 100755 --- a/gryphon/execution/bots/overwatch.py +++ b/gryphon/execution/bots/overwatch.py @@ -220,7 +220,7 @@ def check_spreads_are_normal(db): sanity = True - for exchange_name, fv in native_fvs.iteritems(): + for exchange_name, fv in native_fvs.items(): if abs(fv - current_core_fv) > INTER_EXCHANGE_SPREAD_THRESHOLD: sanity = False break diff --git a/gryphon/execution/bots/shoebox.py b/gryphon/execution/bots/shoebox.py index 0c89cc0..6fb70c7 100755 --- a/gryphon/execution/bots/shoebox.py +++ b/gryphon/execution/bots/shoebox.py @@ -301,7 +301,7 @@ def manual_btc_withdrawals(db): logger.info('Running manual BTC withdrawals') - for name, target in MANUAL_BTC_EXCHANGES.iteritems(): + for name, target in MANUAL_BTC_EXCHANGES.items(): exchange_db = exchange_factory.make_exchange_data_from_key(name, db) if exchange_db.balance['BTC'] > target: withdrawal_amount = exchange_db.balance['BTC'] - target diff --git a/gryphon/execution/controllers/balance.py b/gryphon/execution/controllers/balance.py index 1365c5a..a642e11 100755 --- a/gryphon/execution/controllers/balance.py +++ b/gryphon/execution/controllers/balance.py @@ -1,3 +1,4 @@ +from __future__ import print_function from gryphon.execution.lib.exchange_color import exchange_color from gryphon.lib.exchange.exchange_factory import * from gryphon.lib.logger import get_logger diff --git a/gryphon/execution/controllers/create_dashboard_user.py b/gryphon/execution/controllers/create_dashboard_user.py index 7beefd4..f1141e8 100755 --- a/gryphon/execution/controllers/create_dashboard_user.py +++ b/gryphon/execution/controllers/create_dashboard_user.py @@ -5,11 +5,14 @@ Usage: gryphon-exec create-dashboard-user [--execute] """ +from __future__ import print_function import getpass import termcolor as tc import os +from six.moves import input + from gryphon.lib import session from gryphon.dashboards.models.user import User from gryphon.dashboards.models.columns.password_column import Password @@ -43,29 +46,29 @@ def main(execute): - print tc.colored(WARNING_MESSAGE, 'red') - informed_consent = raw_input(WARNING_PROMPT) + print(tc.colored(WARNING_MESSAGE, 'red')) + informed_consent = input(WARNING_PROMPT).strip() if informed_consent != 'y': - print EXIT_MESSAGE + print(EXIT_MESSAGE) return else: - print CONTINUE_MESSAGE + print(CONTINUE_MESSAGE) dashboard_db = session.get_a_dashboard_db_mysql_session() - username = raw_input(ENTER_USERNAME_MESSAGE) + username = input(ENTER_USERNAME_MESSAGE).strip() password_text = getpass.getpass(ENTER_PASSWORD_MESSAGE) password = Password(plain=password_text) - + user = User(username, password) if execute is True: dashboard_db.add(user) dashboard_db.commit() - print tc.colored(SUCCESS_MESSAGE, 'green') + print(tc.colored(SUCCESS_MESSAGE, 'green')) else: - print SUCCESS_NO_EXECUTE_MESSAGE - + print(SUCCESS_NO_EXECUTE_MESSAGE) + diff --git a/gryphon/execution/controllers/fee_buyback.py b/gryphon/execution/controllers/fee_buyback.py index 78a03c3..dd66301 100755 --- a/gryphon/execution/controllers/fee_buyback.py +++ b/gryphon/execution/controllers/fee_buyback.py @@ -1,3 +1,4 @@ +from __future__ import print_function import prompter import termcolor as tc @@ -14,7 +15,7 @@ def buyback(): prompt_msg = tc.colored('Did you stop the Coinbase Bot before running this?', 'red') bot_stopped = prompter.yesno(prompt_msg) if not bot_stopped: - print tc.colored('Go stop the bot first.', 'red') + print(tc.colored('Go stop the bot first.', 'red')) return db = session.get_a_trading_db_mysql_session() @@ -33,7 +34,7 @@ def buyback(): transactions_buyback_amount = sum([t.fee for t in transactions_with_outstanding_fees]) btc_buyback_amount = trades_buyback_amount + transactions_buyback_amount - print 'Go buy %s on Coinbase (not the exchange)' % btc_buyback_amount + print('Go buy %s on Coinbase (not the exchange)' % btc_buyback_amount) prompt_msg = 'How much USD did it cost (total including Coinbase Fee): USD' raw_usd_cost = prompter.prompt(prompt_msg) diff --git a/gryphon/execution/controllers/initialize_ledger.py b/gryphon/execution/controllers/initialize_ledger.py index 029a8d0..e2d6f4a 100755 --- a/gryphon/execution/controllers/initialize_ledger.py +++ b/gryphon/execution/controllers/initialize_ledger.py @@ -15,6 +15,7 @@ [comma-separated list of exchange pairs, e.g. 'bitstamp_btc_usd,gemini_btc_usd'] [--execute] """ +from __future__ import print_function import pyximport; pyximport.install() @@ -53,7 +54,7 @@ def initialize_exchange_ledger(db, wrapper_obj): pass finally: if db_obj is not None: - print ALREADY_INITIALIZED_ERR_MESSAGE % wrapper_obj.name + print(ALREADY_INITIALIZED_ERR_MESSAGE % wrapper_obj.name) return # Create the entry in the Exchange table. @@ -66,12 +67,12 @@ def initialize_exchange_ledger(db, wrapper_obj): try: balance = wrapper_obj.get_balance() except KeyError as e: - print NO_API_CREDENTIALS_ERR_MESSAGE % wrapper_obj.name - print e + print(NO_API_CREDENTIALS_ERR_MESSAGE % wrapper_obj.name) + print(e) return except Exception as e: - print UNKNOWN_ERR_MESSAGE % wrapper_obj.name - print e + print(UNKNOWN_ERR_MESSAGE % wrapper_obj.name) + print(e) return price_currency = wrapper_obj.currency diff --git a/gryphon/execution/controllers/order_book.py b/gryphon/execution/controllers/order_book.py index 83b3a5e..70539dd 100755 --- a/gryphon/execution/controllers/order_book.py +++ b/gryphon/execution/controllers/order_book.py @@ -1,3 +1,4 @@ +from __future__ import print_function import termcolor as tc from gryphon.execution.lib.exchange_color import exchange_color, legend @@ -96,7 +97,7 @@ def order_book(exchange_name, include_our_orders=False, include_fees=False): for order in asks + bids: order.apply_fee() - print + print() # if we are showing a consolidated orderbook if not exchange_name: print(legend() + "\n") diff --git a/gryphon/execution/harness/exchange_coordinator.pyx b/gryphon/execution/harness/exchange_coordinator.pyx index e36071c..4eb7265 100755 --- a/gryphon/execution/harness/exchange_coordinator.pyx +++ b/gryphon/execution/harness/exchange_coordinator.pyx @@ -15,8 +15,6 @@ exchange. import pyximport; pyximport.install() -from sets import Set - from cdecimal import Decimal, ROUND_UP, ROUND_DOWN from delorean import Delorean from sqlalchemy.orm import joinedload @@ -62,7 +60,7 @@ class ExchangeCoordinator(object): # or audit() for this exchange. Potentially, we could make this even less # strict, setting this to False whenever there are no orders left on the books. self.is_active = False - + """ This actually means that we won't audit in no-execute mode. We do want audits to take place even if nothing has happened... hmm... @@ -81,9 +79,9 @@ class ExchangeCoordinator(object): @tick_profile def _get_current_orders(self, exchange_open_orders): db_open_orders = self._get_db_open_orders() - db_open_order_ids = Set([o.exchange_order_id for o in db_open_orders]) + db_open_order_ids = set([o.exchange_order_id for o in db_open_orders]) - exchange_open_order_ids = Set([o['id'] for o in exchange_open_orders]) + exchange_open_order_ids = set([o['id'] for o in exchange_open_orders]) eaten_order_ids = db_open_order_ids - exchange_open_order_ids current_order_ids = db_open_order_ids & exchange_open_order_ids @@ -144,7 +142,7 @@ class ExchangeCoordinator(object): )[0] # Partially filled. - if (current_order_from_exchange['volume_remaining'] + if (current_order_from_exchange['volume_remaining'] < current_order_from_db.volume_remaining): details_result = self.get_multi_order_details( @@ -225,8 +223,8 @@ class ExchangeCoordinator(object): def update_position(self, position_change, position_change_no_fees): """ Formerly harness:update_position. - """ - for currency_code, position in position_change.iteritems(): + """ + for currency_code, position in position_change.items(): self.exchange_account.position[currency_code] += position self.exchange_account.balance[currency_code] += position @@ -315,7 +313,7 @@ class ExchangeCoordinator(object): '1', self.exchange_wrapper.currency, ).to('USD').amount - + if extra_data: order.datums = self._create_datums_from_extra_data(extra_data) @@ -507,7 +505,7 @@ class ExchangeCoordinator(object): self.reopen_orders(e.exchange, failed_order_ids) # There aren't any open orders because we're in an audit. - eaten_order_ids, current_orders = self._get_current_orders([]) + eaten_order_ids, current_orders = self._get_current_orders([]) self._run_accounting(eaten_order_ids, current_orders) # Now we retry the original audit. If it fails again this will cause a diff --git a/gryphon/execution/lib/auditing.py b/gryphon/execution/lib/auditing.py index 1e5a9dd..3f1571e 100755 --- a/gryphon/execution/lib/auditing.py +++ b/gryphon/execution/lib/auditing.py @@ -150,7 +150,7 @@ def order_audit(db, exchange, skip_recent=0, tolerance=Decimal('0')): failed_order_data = [] - for exchange_order_id, exchange_volume_filled in audit_data.iteritems(): + for exchange_order_id, exchange_volume_filled in audit_data.items(): try: db_volume_filled = db_order_hash[exchange_order_id] @@ -287,7 +287,7 @@ def balance_equality(balance_a, balance_b): are fixing it here with the intention of a later fix to the core lib. """ - currencies = set(balance_a.keys() + balance_b.keys()) + currencies = set(list(balance_a.keys()) + list(balance_b.keys())) for currency in currencies: if currency in balance_a and currency in balance_b: diff --git a/gryphon/execution/lib/config.py b/gryphon/execution/lib/config.py index ffb1d2e..9580330 100755 --- a/gryphon/execution/lib/config.py +++ b/gryphon/execution/lib/config.py @@ -1,4 +1,5 @@ -import ConfigParser +from __future__ import print_function +from six.moves.configparser import RawConfigParser from gryphon.lib.logger import get_logger @@ -6,9 +7,9 @@ def get_config_var(filepath, section, key): - print filepath + print(filepath) - config = ConfigParser.RawConfigParser() + config = RawConfigParser() config.read(filepath) section_dict = dict(config.items('live')) diff --git a/gryphon/execution/lib/config_helper.py b/gryphon/execution/lib/config_helper.py index 4da43d2..ddf0bc3 100755 --- a/gryphon/execution/lib/config_helper.py +++ b/gryphon/execution/lib/config_helper.py @@ -6,7 +6,7 @@ Just a few functions that make our configuration handling cleaner. -The rule is: +The rule is: 1) From any source, if something isn't specified explicitly, it is left out of the dictionary, or put as None, and any other value from any source will override it. @@ -14,7 +14,6 @@ 3) At no point is there a any guarantee a setting is in the configuration object. """ -import ConfigParser import argparse from cdecimal import Decimal, InvalidOperation @@ -70,7 +69,7 @@ def parse_extra_strategy_args(args): """ settings = [x for x in args if x[:2] == '--'] - + parser = argparse.ArgumentParser() for setting_name in settings: @@ -86,7 +85,7 @@ def parse_extra_strategy_args(args): def get_conf_file_configuration(conf_filename, strategy_name): """ If there was a config file specified, load it. If not, look for [strategy_name].conf - in the current directory. If neither is found just return an initialized + in the current directory. If neither is found just return an initialized configuration object that is otherwise empty. """ diff --git a/gryphon/execution/lib/tick_profiling.py b/gryphon/execution/lib/tick_profiling.py index 9595fa7..968fb70 100755 --- a/gryphon/execution/lib/tick_profiling.py +++ b/gryphon/execution/lib/tick_profiling.py @@ -21,7 +21,7 @@ def record_tick_data(tick_start, strategy_name): def record_tick_block_data(algo, tick_count, strategy_name): - for function_name, profile_times in tick_profile_data.iteritems(): + for function_name, profile_times in tick_profile_data.items(): datum_name = datum_name_for_function_block(strategy_name, function_name) for block_time in profile_times: diff --git a/gryphon/execution/live_runner.py b/gryphon/execution/live_runner.py index 78e448d..cd08952 100755 --- a/gryphon/execution/live_runner.py +++ b/gryphon/execution/live_runner.py @@ -1,3 +1,4 @@ +from __future__ import print_function import pyximport; pyximport.install() from cdecimal import Decimal import inspect @@ -253,7 +254,7 @@ def live_run(configuration): while True: try: tick_start = Delorean().epoch - print '\n\n%s' % strategy.name + print('\n\n%s' % strategy.name) if warm_shutdown_flag: return # This takes us into the finally block. diff --git a/gryphon/execution/models/backtesting/result.py b/gryphon/execution/models/backtesting/result.py index f9bee4c..a393a2e 100755 --- a/gryphon/execution/models/backtesting/result.py +++ b/gryphon/execution/models/backtesting/result.py @@ -2,6 +2,7 @@ from datetime import datetime import uuid +from six import text_type from sqlalchemy import Column, Unicode, UnicodeText, DateTime, Integer, Numeric from sqlalchemy.orm import relationship, backref @@ -23,11 +24,11 @@ class Result(Base): _usd = Column('usd', Numeric(precision=20, scale=10)) _btc = Column('btc', Numeric(precision=20, scale=10)) time_created = Column(DateTime, nullable=False) - + trades = relationship('ResultTrade', cascade="all,delete-orphan", backref='result') - + def __init__(self, usd, btc, trading_volume, algorithm, batch, ticks): - self.unique_id = unicode(uuid.uuid4().hex) + self.unique_id = text_type(uuid.uuid4().hex) self.time_created = datetime.utcnow() self.algorithm = algorithm self.batch = batch @@ -35,7 +36,7 @@ def __init__(self, usd, btc, trading_volume, algorithm, batch, ticks): self.btc = btc self.ticks = ticks self.trading_volume = trading_volume - + @property def trading_volume(self): return Money(self._trading_volume, 'BTC') @@ -43,7 +44,7 @@ def trading_volume(self): @trading_volume.setter def trading_volume(self, value): self._trading_volume = value.amount - + @property def btc(self): return Money(self._btc, 'BTC') @@ -59,4 +60,4 @@ def usd(self): @usd.setter def usd(self, value): self._usd = value.amount - + diff --git a/gryphon/execution/scripts/itbit_auth_test.py b/gryphon/execution/scripts/itbit_auth_test.py index 08cdaac..ff91f34 100755 --- a/gryphon/execution/scripts/itbit_auth_test.py +++ b/gryphon/execution/scripts/itbit_auth_test.py @@ -2,6 +2,7 @@ This is a minimal script that demonstrates authentication on itbit. This is useful for debugging if you ever run into issues with authenticating on itbit. """ +from __future__ import print_function import base64 import hashlib @@ -59,5 +60,5 @@ def main(script_arguments, execute): full_url = 'https://api.itbit.com/v1' + url - print requests.get(full_url, data=request_args).text + print(requests.get(full_url, data=request_args).text) diff --git a/gryphon/execution/scripts/ledger_export.py b/gryphon/execution/scripts/ledger_export.py index edf29bc..a2b9354 100755 --- a/gryphon/execution/scripts/ledger_export.py +++ b/gryphon/execution/scripts/ledger_export.py @@ -182,7 +182,7 @@ def table_entries_from_transaction(transaction): entry['date'] = date entry['details'] = ''.join([ '%s:%s ' % (k, v) - for k, v in transaction.transaction_details.iteritems() + for k, v in transaction.transaction_details.items() if k in ['external_transaction_id', 'notes'] and v not in ['xxx'] ]) @@ -238,7 +238,7 @@ def export_ledger_for_exchange(exchange_name, start_time, end_time): fiat_balance, date, ) - + filename = '%s_ledger_%s_%s.csv' % ( exchange_name.lower(), start_time.strftime('%Y-%m-%d'), diff --git a/gryphon/execution/strategies/base.pyx b/gryphon/execution/strategies/base.pyx index ab1d3ec..fed7a2a 100755 --- a/gryphon/execution/strategies/base.pyx +++ b/gryphon/execution/strategies/base.pyx @@ -1,4 +1,3 @@ -import ConfigParser from delorean import Delorean import pickle import random @@ -41,7 +40,7 @@ class Strategy(ConfigurableObject): # Exchanges that the strategy declares it's interested in up-front. It's # convenient to have these at startup sometimes. - self.target_exchanges = [] + self.target_exchanges = [] if strategy_configuration: self.configure(strategy_configuration) @@ -99,8 +98,8 @@ class Strategy(ConfigurableObject): Use it for things that aren't mission-critical, like to make log messages nice. """ return self.__class__.__name__ - - @property + + @property def position(self): if self._position is not None: return self._position diff --git a/gryphon/execution/strategies/builtin/fundamental_value/v1.py b/gryphon/execution/strategies/builtin/fundamental_value/v1.py index 76c1ab9..17c9baa 100755 --- a/gryphon/execution/strategies/builtin/fundamental_value/v1.py +++ b/gryphon/execution/strategies/builtin/fundamental_value/v1.py @@ -30,7 +30,7 @@ def calculate(algo, fundamental_value_balance_map): # Determine which exchanges should participate in the bid and which in the ask # and sum them up appropriately. - for exchange_name, exchange in fundamental_value_balance_map.iteritems(): + for exchange_name, exchange in fundamental_value_balance_map.items(): # You may sell if you have enough bitcoin to place an order and don't have # too much fiat. if (exchange[algo.volume_currency.lower()] > buffer_value and diff --git a/gryphon/execution/strategies/builtin/fundamental_value/v2.py b/gryphon/execution/strategies/builtin/fundamental_value/v2.py index 1526dff..6c8e433 100755 --- a/gryphon/execution/strategies/builtin/fundamental_value/v2.py +++ b/gryphon/execution/strategies/builtin/fundamental_value/v2.py @@ -20,7 +20,7 @@ def calculate(algo, fundamental_value_balance_map): participating_exchanges = [] - for exchange_name, exchange in fundamental_value_balance_map.iteritems(): + for exchange_name, exchange in fundamental_value_balance_map.items(): # If you have bitcoin and are below your maximum fiat, you can sell. can_sell = ( exchange[algo.volume_currency.lower()] > buffer_value and diff --git a/gryphon/execution/strategies/builtin/fundamental_value/v3.py b/gryphon/execution/strategies/builtin/fundamental_value/v3.py index e8b7004..334d8b4 100755 --- a/gryphon/execution/strategies/builtin/fundamental_value/v3.py +++ b/gryphon/execution/strategies/builtin/fundamental_value/v3.py @@ -34,7 +34,7 @@ def calculate(algo, fundamental_value_balance_map): # Determine which exchanges should participate in the bid and which in the ask # and sum them up appropriately. - for exchange_name, exchange in fundamental_value_balance_map.iteritems(): + for exchange_name, exchange in fundamental_value_balance_map.items(): # You may sell if you have enough bitcoin to place an order and don't have # too much fiat. exchange_weight = conf.fv_v3_weights[algo.volume_currency][exchange_name] diff --git a/gryphon/lib/__init__.py b/gryphon/lib/__init__.py index adac250..f345a4f 100755 --- a/gryphon/lib/__init__.py +++ b/gryphon/lib/__init__.py @@ -1,3 +1,4 @@ +from __future__ import print_function __version__ = '0.1' def main(): diff --git a/gryphon/lib/analysis/legacy/average_true_range.py b/gryphon/lib/analysis/legacy/average_true_range.py index b6572ef..2e7a57f 100755 --- a/gryphon/lib/analysis/legacy/average_true_range.py +++ b/gryphon/lib/analysis/legacy/average_true_range.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np from exponential_moving_average import ExpMovingAverage @@ -12,9 +13,9 @@ def TR(d,c,h,l,o,yc): y = abs(h-yc) z = abs(l-yc) - print x - print y - print z + print(x) + print(y) + print(z) if y <= x >= z: TR = x @@ -23,7 +24,7 @@ def TR(d,c,h,l,o,yc): elif x <= z >= y: TR = z - print d, TR + print(d, TR) return d, TR x = 1 @@ -39,7 +40,7 @@ def TR(d,c,h,l,o,yc): -print len(TrueRanges) +print(len(TrueRanges)) ATR = ExpMovingAverage(TrueRanges,14) -print ATR +print(ATR) diff --git a/gryphon/lib/analysis/legacy/chaikin_volatility.py b/gryphon/lib/analysis/legacy/chaikin_volatility.py index fa0f210..609b342 100755 --- a/gryphon/lib/analysis/legacy/chaikin_volatility.py +++ b/gryphon/lib/analysis/legacy/chaikin_volatility.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np import time @@ -32,10 +33,10 @@ def chaikinVolCalc(emaUsed,periodsAgo): highMlow.append(hml) x += 1 - print len(date) - print len(highMlow) + print(len(date)) + print(len(highMlow)) highMlowEMA = ExpMovingAverage(highMlow,emaUsed) - print len(highMlowEMA) + print(len(highMlowEMA)) y = emaUsed + periodsAgo while y < len(date): @@ -43,7 +44,7 @@ def chaikinVolCalc(emaUsed,periodsAgo): chaikin_volatility.append(cvc) y+=1 - print len(date[emaUsed+periodsAgo:]) + print(len(date[emaUsed+periodsAgo:])) return date[emaUsed+periodsAgo:], chaikin_volatility diff --git a/gryphon/lib/analysis/legacy/chart.py b/gryphon/lib/analysis/legacy/chart.py index b5d121f..a4ce791 100755 --- a/gryphon/lib/analysis/legacy/chart.py +++ b/gryphon/lib/analysis/legacy/chart.py @@ -61,6 +61,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' +from __future__ import print_function +from __future__ import absolute_import import urllib2 import time @@ -72,8 +74,8 @@ from matplotlib.finance import candlestick import matplotlib import pylab -from simple_moving_average import movingaverage -from rsi import rsiFunc +from .simple_moving_average import movingaverage +from .rsi import rsiFunc matplotlib.rcParams.update({'font.size': 9}) @@ -207,8 +209,8 @@ def graphData(stock,MA1,MA2): plt.show() fig.savefig('example.png',facecolor=fig.get_facecolor()) - except Exception,e: - print 'main loop',str(e) + except Exception as e: + print('main loop',str(e)) while True: graphData('YHOO',10,50) diff --git a/gryphon/lib/analysis/legacy/ease_of_movement.py b/gryphon/lib/analysis/legacy/ease_of_movement.py index a33bb1e..0201e64 100755 --- a/gryphon/lib/analysis/legacy/ease_of_movement.py +++ b/gryphon/lib/analysis/legacy/ease_of_movement.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np import time @@ -25,13 +26,13 @@ def EMV(d,c,h,l,o,v,tf): boxr = ( (v[x]/1000000.00)/ (h[x]-l[x]) ) OnepEMVs = movement / boxr OnepEMV.append(OnepEMVs) - print OnepEMVs + print(OnepEMVs) x += 1 tfEMV = movingaverage(OnepEMV,tf) - print len(tfEMV) - print len(d[tf:]) + print(len(tfEMV)) + print(len(d[tf:])) return d[tf:],tfEMV diff --git a/gryphon/lib/analysis/legacy/elder_force_index.py b/gryphon/lib/analysis/legacy/elder_force_index.py index 408620c..45daac5 100755 --- a/gryphon/lib/analysis/legacy/elder_force_index.py +++ b/gryphon/lib/analysis/legacy/elder_force_index.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np import time @@ -23,7 +24,7 @@ def EFI(d,c,v,tf): x = 1 while x < len(d): forceIndex = (c[x] - c[x-1]) * v[x] - print forceIndex + print(forceIndex) efi.append(forceIndex) x+=1 efitf = ExpMovingAverage(efi,tf) diff --git a/gryphon/lib/analysis/legacy/gapo.py b/gryphon/lib/analysis/legacy/gapo.py index ab5e4cc..ca0c077 100755 --- a/gryphon/lib/analysis/legacy/gapo.py +++ b/gryphon/lib/analysis/legacy/gapo.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np import time import math @@ -23,7 +24,7 @@ def GAPO(d,h,l,tf): gapos = ( (math.log(HighestHigh - LowestLow)) / math.log(tf)) - print gapos + print(gapos) gapo.append(gapos) x+=1 return d[tf:],gapo diff --git a/gryphon/lib/analysis/legacy/swing_index.py b/gryphon/lib/analysis/legacy/swing_index.py index 0ce4d21..d465850 100755 --- a/gryphon/lib/analysis/legacy/swing_index.py +++ b/gryphon/lib/analysis/legacy/swing_index.py @@ -1,3 +1,4 @@ +from __future__ import print_function #November 11th 2013: open1 = 1286.50 high1 = 1287.70 @@ -18,25 +19,25 @@ def calc_R(H2,C1,L2,O1,LM): x = H2-C1 y = L2-C1 z = H2-L2 - print x - print y - print z + print(x) + print(y) + print(z) if z < x > y: - print 'x wins!' + print('x wins!') R = (H2-C1)-(.5*(L2-C1))+(.25*(C1-O1)) - print R + print(R) return R elif x < y > z: - print 'y wins!' + print('y wins!') R = (L2-C1)-(.5*(H2-C1))+(.25*(C1-O1)) - print R + print(R) return R elif x < z > y: - print 'z wins!' + print('z wins!') R = (H2-L2)+(.25*(C1-O1)) - print R + print(R) return R @@ -46,11 +47,11 @@ def calc_K(H2,L2,C1): if x > y: K=x - print K + print(K) return K elif x < y: K=y - print K + print(K) return K L = LM @@ -58,8 +59,8 @@ def calc_K(H2,L2,C1): K = calc_K(H2,L2,C1) SwIn = 50*((C2-C1+(.5*(C2-O2))+(.25*(C1-O1)))/R)*(K/L) - print '###' - print SwIn + print('###') + print(SwIn) diff --git a/gryphon/lib/analysis/legacy/volatility.py b/gryphon/lib/analysis/legacy/volatility.py index 9bba332..b33af31 100755 --- a/gryphon/lib/analysis/legacy/volatility.py +++ b/gryphon/lib/analysis/legacy/volatility.py @@ -339,15 +339,15 @@ def volatility(values, timestamps, window_time=10000): for j in range(len(timestamps)): index = j+i if index > len(timestamps)-1: - break + break elif noted_timestamp - timestamps[index] < window_time: relevant_values.append(values[index]) relevant_timestamps.append(noted_timestamp - timestamps[index]) else: break - - standard_deviation = np.std(relevant_values) - mean = np.mean(relevant_values) + + standard_deviation = numpy.std(relevant_values) + mean = numpy.mean(relevant_values) #volatility = Decimal(standard_deviation)/Decimal(mean) vols.append(standard_deviation) vols.reverse() diff --git a/gryphon/lib/bitcoinwisdom.py b/gryphon/lib/bitcoinwisdom.py index dc2271a..c837167 100755 --- a/gryphon/lib/bitcoinwisdom.py +++ b/gryphon/lib/bitcoinwisdom.py @@ -23,7 +23,7 @@ def __init__(self, exchange='bitstamp'): self.symbol = 'btccad' elif self.exchange == 'kraken': self.symbol = 'btceur' - + self.steps ={ '1m': 60,'3m': 180,'5m': 300,'15m': 900,'30m':1800, '1h':3600,'2h':7200,'4h':14400,'6h':21600,'12h':43200, @@ -32,7 +32,7 @@ def __init__(self, exchange='bitstamp'): # currently caching for a day, maybe longer in the future @cache_me(time=86400, ignore_self=True) - def req_with_cache(self, url): + def req_with_cache(self, url): return self.req(url) def req(self, url): @@ -47,7 +47,7 @@ def create_url(self, step): url = 'period?step=%s&symbol=%s%s' % (step_seconds, self.exchange, self.symbol) url = self.base_url % url return url - + def determine_step(self, start_date, end_date): if (end_date - start_date) >= timedelta(days=1): step = '1d' @@ -56,8 +56,8 @@ def determine_step(self, start_date, end_date): else: step = '1m' return step - - + + def period(self, start_date, end_date, step='1d', sid=''): if self.should_cache_this_result(start_date, end_date): points = self.req_with_cache(self.create_url(step)) @@ -70,7 +70,7 @@ def period(self, start_date, end_date, step='1d', sid=''): for p in points: point_hash[epoch(p[0]).naive] = Money(str(p[7]), 'BTC') return point_hash - + def volume_in_period(self, start_date, end_date): start_date = Delorean(start_date, 'UTC').datetime @@ -83,7 +83,7 @@ def volume_in_period(self, start_date, end_date): step=self.determine_step(start_date, end_date), ) - for k,v in periods.iteritems(): + for k, v in periods.items(): t=Delorean(k, 'UTC').datetime vol=v if t >= start_date and t < end_date: diff --git a/gryphon/lib/configuration.py b/gryphon/lib/configuration.py index c3547f4..2d9c496 100755 --- a/gryphon/lib/configuration.py +++ b/gryphon/lib/configuration.py @@ -4,8 +4,8 @@ import argparse from collections import defaultdict -import ConfigParser -import StringIO +import six +from six.moves.configparser import ConfigParser, RawConfigParser from cdecimal import Decimal, InvalidOperation @@ -19,7 +19,7 @@ def read_config_from_file(config_filename): Section titles of the form [x:y] are parsed into sub-dictionaries under the key x. """ - parser = ConfigParser.RawConfigParser() + parser = RawConfigParser() parser.read(config_filename) configuration = parse_sections(parser) @@ -31,8 +31,8 @@ def _get_parser_for_string_config(string_config): """ This should only be used for unit testing. """ - buf = StringIO.StringIO(string_config) - parser = ConfigParser.ConfigParser() + buf = six.StringIO(string_config) + parser = ConfigParser() parser.readfp(buf) return parser @@ -112,6 +112,6 @@ def dict_update_override(dicta, dictb): iii) does override a valid value in a with a valid value from b """ dicta.update( - {k: v for k, v in dictb.iteritems() if v or (k not in dicta)} + {k: v for k, v in dictb.items() if v or (k not in dicta)} ) diff --git a/gryphon/lib/debugging/bitstamp_cert_error.py b/gryphon/lib/debugging/bitstamp_cert_error.py index 7b28087..e33709f 100755 --- a/gryphon/lib/debugging/bitstamp_cert_error.py +++ b/gryphon/lib/debugging/bitstamp_cert_error.py @@ -1,7 +1,7 @@ """ Prepared by Gareth MacLeod, 3 April 2018. -This demonstrates that python 2.7 is having series issues with authenticated requests +This demonstrates that python 2.7 is having series issues with authenticated requests to the bitstamp API. This script fails on fresh installs of Ubuntu 14.04 LTS and 16 LTS. The deepest I've gotten into this bug is this: the requests.Session() object can make @@ -44,6 +44,7 @@ Make sure you have yoru bitstamp credentials in a .env file in the directory you are running from. """ +from __future__ import print_function import requests import hmac @@ -54,6 +55,7 @@ import dotenv import os import os.path +from six import text_type dotenv_path = os.path.join(os.path.dirname(__file__), '.env') dotenv.load_dotenv(dotenv_path) @@ -67,10 +69,10 @@ def requests_dot_post(): - print '---' - print "Trying requests.post" + print('---') + print("Trying requests.post") - nonce = unicode(int(round(time.time() * 1000))) + nonce = text_type(int(round(time.time() * 1000))) message = nonce + CLIENT_ID + API_KEY sig = hmac.new(SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper() @@ -82,30 +84,30 @@ def requests_dot_post(): result = requests.post(API_BALANCE_URL, data=payload).text - print 'Response from bitstamp: %s' % result[:50] + print('Response from bitstamp: %s' % result[:50]) try: assert('btc_available' in result) - print 'requests.post succeeded!' + print('requests.post succeeded!') except Exception as e: - print 'requests.post failed: %s' % str(e) + print('requests.post failed: %s' % str(e)) def session_post(session=None, clear_cookies=None): - print '---' + print('---') if session is None: - print "Trying with a new session" + print("Trying with a new session") session = requests.Session() else: - print "Trying with an extant session" + print("Trying with an extant session") if clear_cookies is True: - print "Clearing the session's cookies" + print("Clearing the session's cookies") session.cookies.clear() - nonce = unicode(int(round(time.time() * 1000))) + nonce = text_type(int(round(time.time() * 1000))) message = nonce + CLIENT_ID + API_KEY sig = hmac.new(SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper() @@ -117,13 +119,13 @@ def session_post(session=None, clear_cookies=None): result = session.post(API_BALANCE_URL, payload).text - print 'Response from bitstamp: %s' % result[:50] + print('Response from bitstamp: %s' % result[:50]) try: assert('btc_available' in result) - print 'Session succeeded!' + print('Session succeeded!') except Exception as e: - print 'Session failed: %s' % str(e) + print('Session failed: %s' % str(e)) return session diff --git a/gryphon/lib/exchange/bitfinex_btc_usd.py b/gryphon/lib/exchange/bitfinex_btc_usd.py index 4c5f148..f002667 100755 --- a/gryphon/lib/exchange/bitfinex_btc_usd.py +++ b/gryphon/lib/exchange/bitfinex_btc_usd.py @@ -9,6 +9,7 @@ import cdecimal from cdecimal import Decimal from delorean import Delorean, parse +from six import string_types, text_type from gryphon.lib.exchange import exceptions from gryphon.lib.exchange.consts import Consts @@ -90,13 +91,13 @@ def trades_for_orders_req(self): return self.all_trades_req() def trades_for_orders_resp(self, req, order_ids): - order_ids = [unicode(o) for o in order_ids] + order_ids = [text_type(o) for o in order_ids] trades = self.all_trades_resp(req) matching_trades = {} for trade in trades: - oid = unicode(trade['order_id']) + oid = text_type(trade['order_id']) if oid in order_ids: if not oid in matching_trades: matching_trades[oid] = [] @@ -262,7 +263,7 @@ def multi_order_details_req(self): return self.trades_for_orders_req() def multi_order_details_resp(self, req, order_ids): - order_ids = [unicode(o) for o in order_ids] + order_ids = [text_type(o) for o in order_ids] multi_trades = self.trades_for_orders_resp(req, order_ids) data = {} @@ -294,7 +295,7 @@ def multi_order_details_resp(self, req, order_ids): our_trades.append({ 'time': int(float(t['timestamp'])), - 'trade_id': unicode(t['tid']), + 'trade_id': text_type(t['tid']), 'fee': fee, 'btc': btc_amount, 'fiat': usd_amount, @@ -328,7 +329,7 @@ def cancel_order_resp(self, req): return {'success': True} def withdraw_crypto_req(self, address, volume): - if not isinstance(address, basestring): + if not isinstance(address, string_types): raise TypeError('Withdrawal address must be a string') if not isinstance(volume, Money) or volume.currency != 'BTC': diff --git a/gryphon/lib/exchange/bitme.py b/gryphon/lib/exchange/bitme.py index ca11d00..953f044 100755 --- a/gryphon/lib/exchange/bitme.py +++ b/gryphon/lib/exchange/bitme.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import time import os import datetime @@ -15,9 +16,9 @@ from gryphon.lib.exchange.consts import Consts from gryphon.lib.money import Money -from base import * -from exceptions import * -from exchange_order import Order +from .base import * +from .exceptions import * +from .exchange_order import Order from gryphon.lib.models.exchange import Balance from cdecimal import * diff --git a/gryphon/lib/exchange/buttercoin.py b/gryphon/lib/exchange/buttercoin.py index f8d38b6..728cf79 100755 --- a/gryphon/lib/exchange/buttercoin.py +++ b/gryphon/lib/exchange/buttercoin.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import time import os import datetime @@ -14,9 +15,9 @@ from gryphon.lib.exchange.consts import Consts from gryphon.lib.money import Money -from base import * -from exceptions import * -from exchange_order import Order +from .base import * +from .exceptions import * +from .exchange_order import Order from gryphon.lib.models.exchange import Balance from gryphon.lib.models.datum import DatumRecorder diff --git a/gryphon/lib/exchange/cavirtex.py b/gryphon/lib/exchange/cavirtex.py index 6e0cc14..682aa35 100755 --- a/gryphon/lib/exchange/cavirtex.py +++ b/gryphon/lib/exchange/cavirtex.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import time import os import datetime @@ -15,9 +16,9 @@ from gryphon.lib.exchange.consts import Consts from gryphon.lib.money import Money -from exchange_order import Order -from base import * -from exceptions import * +from .exchange_order import Order +from .base import * +from .exceptions import * from gryphon.lib.models.exchange import Balance from cdecimal import * diff --git a/gryphon/lib/exchange/coinbase_btc_usd.py b/gryphon/lib/exchange/coinbase_btc_usd.py index dd5b44f..636eed7 100755 --- a/gryphon/lib/exchange/coinbase_btc_usd.py +++ b/gryphon/lib/exchange/coinbase_btc_usd.py @@ -12,6 +12,7 @@ from cdecimal import Decimal import coinbase.client +from six import string_types, text_type from gryphon.lib.exchange import exceptions from gryphon.lib.exchange import order_types @@ -298,7 +299,7 @@ def auth_request(self, req_method, url, request_args): self.load_creds() req_method = req_method.upper() - timestamp = unicode(int(round(time.time()))) + timestamp = text_type(int(round(time.time()))) # This has already been dumped to json by req(). body = request_args['data'] @@ -538,7 +539,7 @@ def cancel_order_resp(self, req): raise exceptions.CancelOrderNotFoundError() def withdraw_crypto(self, address, volume): - if not isinstance(address, basestring): + if not isinstance(address, string_types): raise TypeError('Withdrawal address must be a string') if not isinstance(volume, Money) or volume.currency != 'BTC': diff --git a/gryphon/lib/exchange/itbit_btc_usd.py b/gryphon/lib/exchange/itbit_btc_usd.py index 4634c99..d1c5621 100755 --- a/gryphon/lib/exchange/itbit_btc_usd.py +++ b/gryphon/lib/exchange/itbit_btc_usd.py @@ -13,6 +13,7 @@ import cdecimal from cdecimal import Decimal +from six import string_types from gryphon.lib.exchange import exceptions from gryphon.lib.exchange import order_types @@ -438,7 +439,7 @@ def cancel_order_resp(self, req): return {'success': True} def withdraw_crypto_req(self, address, volume): - if not isinstance(address, basestring): + if not isinstance(address, string_types): raise TypeError('Withdrawal address must be a string') if not isinstance(volume, Money) or volume.currency != self.volume_currency: @@ -469,7 +470,7 @@ def get_order_audit_data(self, skip_recent=0, page=1): Dropped the skip_recent flag because we don't seem to be using it anywhere. """ if skip_recent != 0: - raise ValueEror('skip_recent is deprecated') + raise ValueError('skip_recent is deprecated') orders = OrderedDict() trades_to_audit = self.all_trades(page=page) diff --git a/gryphon/lib/exchange/kraken_btc_eur.py b/gryphon/lib/exchange/kraken_btc_eur.py index 5437039..db91471 100755 --- a/gryphon/lib/exchange/kraken_btc_eur.py +++ b/gryphon/lib/exchange/kraken_btc_eur.py @@ -10,6 +10,7 @@ from cdecimal import Decimal from delorean import Delorean from more_itertools import chunked +from six import string_types, text_type from gryphon.lib.exchange import exceptions from gryphon.lib.exchange import order_types @@ -147,7 +148,7 @@ def get_trades_info_from_ledger(self, trade_ids, order_open_timestamp, order_clo 'fiat_fee': Money(0, self.currency), } - for ledger_id, entry in entries.iteritems(): + for ledger_id, entry in entries.items(): trade_id = entry['refid'] if trade_id not in trade_ids: @@ -263,7 +264,7 @@ def closed_orders_resp(self, req): count = int(response['count']) closed_orders = [] - for order_id, raw_order in response['closed'].iteritems(): + for order_id, raw_order in response['closed'].items(): raw_order['order_id'] = order_id closed_orders.append(raw_order) @@ -288,7 +289,7 @@ def auth_request(self, req_method, url, request_args): endpoint = url.replace(self.base_url, '') endpoint = '/0' + endpoint - nonce = unicode(int(round(time.time() * 1000))) + nonce = text_type(int(round(time.time() * 1000))) try: payload = request_args['data'] @@ -374,8 +375,8 @@ def place_order_req(self, mode, volume, price, order_type=order_types.LIMIT_ORDE 'pair': self.pair, 'type': mode, 'ordertype': 'limit', - 'price': unicode(price.amount), - 'volume': unicode(volume.amount), + 'price': text_type(price.amount), + 'volume': text_type(volume.amount), } except AttributeError: @@ -387,7 +388,7 @@ def place_order_resp(self, req): response = self.resp(req) try: - return {'success': True, 'order_id': unicode(response['txid'][0])} + return {'success': True, 'order_id': text_type(response['txid'][0])} except KeyError: raise exceptions.ExchangeAPIErrorException( self, @@ -405,7 +406,7 @@ def get_open_orders_resp(self, req): try: raw_open_orders = response['open'] - for order_id, raw_order in raw_open_orders.iteritems(): + for order_id, raw_order in raw_open_orders.items(): if raw_order['status'] == 'open': mode = self._order_mode_to_const(raw_order['descr']['type']) volume = Money(raw_order['vol'], 'BTC') @@ -437,13 +438,13 @@ def get_order_details_req(self, order_id): def get_order_details_resp(self, req, order_id): return self.get_multi_order_details_resp(req, [order_id])[order_id] - + def get_multi_order_details(self, order_ids): req = self.get_multi_order_details_req(order_ids) return self.get_multi_order_details_resp(req, order_ids) - + def get_multi_order_details_req(self, order_ids): - order_ids = [unicode(o) for o in order_ids] + order_ids = [text_type(o) for o in order_ids] payload = { 'trades': True, @@ -482,7 +483,7 @@ def get_multi_order_details_resp(self, req, order_ids): closetm, ) - for t_id, t in trades.iteritems(): + for t_id, t in trades.items(): fiat = abs(t['fiat']) btc = abs(t['btc']) @@ -504,7 +505,7 @@ def get_multi_order_details_resp(self, req, order_ids): our_trades.append({ 'time': int(t['time']), - 'trade_id': unicode(t_id), + 'trade_id': text_type(t_id), 'fee': fee, 'btc': btc, 'fiat': fiat, @@ -522,7 +523,7 @@ def get_multi_order_details_resp(self, req, order_ids): def cancel_order_req(self, order_id): payload = { - 'txid': unicode(order_id), + 'txid': text_type(order_id), } return self.req('post', '/private/CancelOrder', data=payload) @@ -539,7 +540,7 @@ def cancel_order_resp(self, req): ) def withdraw_crypto_req(self, address, volume): - if not isinstance(address, basestring): + if not isinstance(address, string_types): raise TypeError('Withdrawal address must be a string') if self.volume_currency != 'BTC': @@ -554,12 +555,12 @@ def withdraw_crypto_req(self, address, volume): # find the corresponding exchange name, which we then pass to Kraken. deposit_addresses = { name: addr - for name, addr in os.environ.iteritems() if '_DEPOSIT_ADDRESS' in name + for name, addr in os.environ.items() if '_DEPOSIT_ADDRESS' in name } address_to_name_map = { addr: name.replace('_DEPOSIT_ADDRESS', '') - for name, addr in deposit_addresses.iteritems() + for name, addr in deposit_addresses.items() } try: diff --git a/gryphon/lib/exchange/okcoin_btc_usd.py b/gryphon/lib/exchange/okcoin_btc_usd.py index 63afabd..beb1ff6 100755 --- a/gryphon/lib/exchange/okcoin_btc_usd.py +++ b/gryphon/lib/exchange/okcoin_btc_usd.py @@ -5,6 +5,7 @@ import cdecimal from cdecimal import Decimal from delorean import Delorean, parse +from six import string_types from gryphon.lib.exchange import exceptions from gryphon.lib.exchange.consts import Consts @@ -138,7 +139,7 @@ def ticker_resp(self, req): def all_transactions(self, page=0, unfilled_orders=None): req = self.all_transactions_req( - page=page, + page=page, unfilled_orders=unfilled_orders ) @@ -183,7 +184,7 @@ def auth_request(self, req_method, url, request_args): payload = request_args['data'] except KeyError: payload = request_args['data'] = {} - + payload.update({ 'api_key': self.api_key, }) @@ -232,7 +233,7 @@ def balance_resp(self, req): def _get_order_book_req(self, verify=True): return self.req('get', '/depth.do', no_auth=True, verify=verify) - + def create_trade_req(self, mode, volume, price, is_market_order=False): volume = self.round(volume) price = self.round(price) @@ -257,7 +258,7 @@ def create_trade_resp(self, req): try: return { - 'success': True, + 'success': True, 'order_id': str(response['order_id']) } @@ -283,7 +284,7 @@ def order_fee_req(self, order_id): def order_fee_resp(self, req): try: response = self.resp(req) - except CancelOrderNotFoundError: + except exceptions.CancelOrderNotFoundError: # OkCoin has started returning this error on non-executed orders or orders # with no fees. return Money('0', 'USD') @@ -418,7 +419,7 @@ def multi_order_details_resp(self, reqs, order_ids_not_used): for order_id, req in reqs['fees'].items(): response = self.order_fee_resp(req) fees[order_id] = response - + data = {} for raw_order in raw_orders: @@ -431,7 +432,7 @@ def multi_order_details_resp(self, reqs, order_ids_not_used): def parse_raw_order(self, raw_order, fee): mode = self._order_mode_to_const(raw_order['type']) - + timestamp = int(float(raw_order['create_date'])) / 1000 btc_total = Money(raw_order['deal_amount'], 'BTC') @@ -440,7 +441,7 @@ def parse_raw_order(self, raw_order, fee): total_usd = self.round(avg_price * btc_total.amount) # okcoin does not have seperate notions of trade and raw_order - # so if we see a partially filled raw_order here, treat it as a + # so if we see a partially filled raw_order here, treat it as a # full trade trades = [] @@ -452,7 +453,7 @@ def parse_raw_order(self, raw_order, fee): 'fee': fee, 'btc': btc_total, 'fiat': total_usd, - } + } trades.append(fake_trade) @@ -468,7 +469,7 @@ def parse_raw_order(self, raw_order, fee): return order def cancel_order_req(self, order_id): - payload = { + payload = { 'symbol': 'btc_usd', 'order_id': order_id, } @@ -480,7 +481,7 @@ def cancel_order_resp(self, req): return {'success': True} def withdraw_crypto_req(self, address, volume): - if not isinstance(address, basestring): + if not isinstance(address, string_types): raise TypeError('Withdrawal address must be a string') if not isinstance(volume, Money) or volume.currency != self.volume_currency: @@ -526,7 +527,7 @@ def audit(self, skip_recent=0): status = order['status'] volume_filled = Money(order['deal_amount'], 'BTC') - if (status == self.ORDER_STATUS_PARTIALLY_FILLED + if (status == self.ORDER_STATUS_PARTIALLY_FILLED or status == self.ORDER_STATUS_FULLY_FILLED): orders[order_id] = volume_filled diff --git a/gryphon/lib/exchange/poloniex_eth_btc.py b/gryphon/lib/exchange/poloniex_eth_btc.py index 3ed8b1b..160d1be 100755 --- a/gryphon/lib/exchange/poloniex_eth_btc.py +++ b/gryphon/lib/exchange/poloniex_eth_btc.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import base64 from collections import OrderedDict import decimal @@ -9,8 +10,8 @@ from cdecimal import * -from base import * -from exceptions import * +from .base import * +from .exceptions import * from gryphon.lib.models.exchange import Balance from gryphon.lib.money import Money diff --git a/gryphon/lib/exchange/vault_of_satoshi.py b/gryphon/lib/exchange/vault_of_satoshi.py index 27aa51c..cddadfd 100755 --- a/gryphon/lib/exchange/vault_of_satoshi.py +++ b/gryphon/lib/exchange/vault_of_satoshi.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import time import os import datetime @@ -15,10 +16,10 @@ from gryphon.lib.money import Money from gryphon.lib.models.datum import DatumRecorder -from exchange_order import Order +from .exchange_order import Order from gryphon.lib.exchange.consts import Consts -from base import * -from exceptions import * +from .base import * +from .exceptions import * from gryphon.lib.models.exchange import Balance from gryphon.lib.logger import get_logger diff --git a/gryphon/lib/gryphonfury/fees.py b/gryphon/lib/gryphonfury/fees.py index a2a8256..e3e08c0 100755 --- a/gryphon/lib/gryphonfury/fees.py +++ b/gryphon/lib/gryphonfury/fees.py @@ -2,6 +2,8 @@ from sqlalchemy import func +#from gryphon.lib.gryphonfury.revenue import (get_start_and_end_position, +# get_start_and_end_position_trades) from gryphon.lib.logger import get_logger from gryphon.lib.models.order import Order from gryphon.lib.models.trade import Trade @@ -97,6 +99,9 @@ def get_matched_trading_fees_in_period(db, start_time, end_time): of the period are removed. """ + global get_start_and_end_position # workaround for circular imports + global get_start_and_end_position_trades # workaround for circular imports + fees = get_all_fees_in_period_in_usd(db, start_time, end_time) start_position, end_position = get_start_and_end_position(db, start_time, end_time) diff --git a/gryphon/lib/gryphonfury/revenue.py b/gryphon/lib/gryphonfury/revenue.py index bd7a6fe..538ebf6 100755 --- a/gryphon/lib/gryphonfury/revenue.py +++ b/gryphon/lib/gryphonfury/revenue.py @@ -28,7 +28,7 @@ def fast_revenue_in_period(db, start_time, end_time): better queries. Previous function is roughly O(n^2) in the number of trades in the period and this one is likely O(logn) for a low constant. - Refer to the helper function + Refer to the helper function get_revenue_in_period_given_positions_and_position_trades to see the heavy lifting """ @@ -341,7 +341,7 @@ def open_pl(open_position_trades, fundamental_value, price_currency=None, volume Take in an open_position_trades object and the current fundamental value, and use that to calculate our current unrealized profit on that position. This is done simply because the fiat position on those open_position_trades is the price we - paid to open that position, and then the unrealized profit is our current + paid to open that position, and then the unrealized profit is our current expectation of the value of that position (position * fundamental_value). """ @@ -592,12 +592,12 @@ def open_position_trades(open_position_offset, db, start_time, volume_currency=' # Filter out trades we already got. query = query.filter( ~Trade.unique_id.in_([t.unique_id for t in open_position_trades]) - ) + ) trades_batch = query.limit(10).all() for trade in trades_batch: - if (sum([t.volume for t in open_position_trades]) + if (sum([t.volume for t in open_position_trades]) < abs(open_position_offset)): open_position_trades.append(trade) diff --git a/gryphon/lib/hackernewsie.py b/gryphon/lib/hackernewsie.py index 666600c..c6cf29c 100755 --- a/gryphon/lib/hackernewsie.py +++ b/gryphon/lib/hackernewsie.py @@ -27,7 +27,7 @@ def get_hn_breaking_news(keywords={'bitcoin': 3, 'bitstamp': 0}): one_day_ago = Delorean().last_day(1).epoch - for keyword, upvote_threshold in keywords.iteritems(): + for keyword, upvote_threshold in keywords.items(): # We quote the keywords so they don't match things that are close # Prompted by Bitcoin matching Ditchin (https://news.ycombinator.com/item?id=10850368) keyword = '"%s"' % keyword diff --git a/gryphon/lib/models/atlaszero/base.py b/gryphon/lib/models/atlaszero/base.py index 6b768cf..4d2e807 100755 --- a/gryphon/lib/models/atlaszero/base.py +++ b/gryphon/lib/models/atlaszero/base.py @@ -4,6 +4,7 @@ # share some table names. # Reference: http://stackoverflow.com/questions/8264686/sqlalchemy-multiple-databases-with-same-table-names-not-working +from six import text_type from sqlalchemy.ext.declarative import declarative_base AtlasZeroBase = declarative_base() @@ -11,7 +12,7 @@ def unicode_string(self): - return unicode(self).encode('utf-8') + return text_type(self).encode('utf-8') AtlasZeroBase.__str__ == unicode_string diff --git a/gryphon/lib/models/atlaszero/metric.py b/gryphon/lib/models/atlaszero/metric.py index ddddb30..6d99313 100755 --- a/gryphon/lib/models/atlaszero/metric.py +++ b/gryphon/lib/models/atlaszero/metric.py @@ -1,13 +1,15 @@ +from __future__ import absolute_import import json from datetime import datetime import numpy as np import pandas as pd +from six import text_type from sqlalchemy.dialects.mysql import DATETIME from sqlalchemy import Column, Integer, Numeric, Index, DateTime -from metric_types import get_metric_type_int -from base import AtlasZeroBase +from .metric_types import get_metric_type_int +from .base import AtlasZeroBase metadata = AtlasZeroBase.metadata @@ -34,7 +36,7 @@ def __init__(self, metric_type, value, timestamp): self.value = value def __unicode__(self): - return unicode(repr(self)) + return text_type(repr(self)) def __repr__(self): d = { diff --git a/gryphon/lib/models/atlaszero/metric_types.py b/gryphon/lib/models/atlaszero/metric_types.py index 4923ade..a2d547b 100755 --- a/gryphon/lib/models/atlaszero/metric_types.py +++ b/gryphon/lib/models/atlaszero/metric_types.py @@ -1,3 +1,4 @@ +from __future__ import print_function from gryphon.lib.exchange.exchange_factory import ALL_EXCHANGE_KEYS as all_exchanges from gryphon.lib.util.list import distinct @@ -5534,7 +5535,7 @@ def generate_initial_series_name_list(): for st in series_types_orderbook_data: for exchange in all_exchanges: for depth in depths_on_orderbook_data: - print " '%s-%s-%s': %s," % (st, exchange, depth, count) + print(" '%s-%s-%s': %s," % (st, exchange, depth, count)) count += 1 series_types_on_trade_data = ['volume', 'vwap'] @@ -5543,5 +5544,5 @@ def generate_initial_series_name_list(): for st in series_types_on_trade_data: for exchange in all_exchanges: for info in info_on_trade_data: - print " '%s-%s-%s': %s," % (st, exchange, info, count) + print(" '%s-%s-%s': %s," % (st, exchange, info, count)) count += 1 diff --git a/gryphon/lib/models/datum.py b/gryphon/lib/models/datum.py index 34b6c72..6950e0a 100755 --- a/gryphon/lib/models/datum.py +++ b/gryphon/lib/models/datum.py @@ -4,6 +4,7 @@ import uuid from cdecimal import Decimal +from six import text_type from sqlalchemy import ForeignKey, Column, Integer, Unicode, DateTime, UnicodeText, Numeric from gryphon.lib.models.base import Base @@ -31,17 +32,17 @@ def __init__(self, datum_type, numeric_value=None, string_value=None, meta_data= self.datum_type = datum_type self.numeric_value = numeric_value self.string_value = string_value - self.unique_id = u'dat_%s' % unicode(uuid.uuid4().hex) + self.unique_id = u'dat_%s' % text_type(uuid.uuid4().hex) self.meta_data = json.dumps(meta_data) self.order = order def __unicode__(self): - return unicode(repr(self)) + return text_type(repr(self)) def __repr__(self): d = { 'datum_type': self.datum_type, - 'time_created': unicode(self.time_created), + 'time_created': text_type(self.time_created), 'meta_data': json.loads(self.meta_data), } if self.numeric_value: diff --git a/gryphon/lib/models/emeraldhavoc/base.py b/gryphon/lib/models/emeraldhavoc/base.py index 179153b..949c1c6 100755 --- a/gryphon/lib/models/emeraldhavoc/base.py +++ b/gryphon/lib/models/emeraldhavoc/base.py @@ -4,15 +4,16 @@ # names. # Reference: http://stackoverflow.com/questions/8264686/sqlalchemy-multiple-databases-with-same-table-names-not-working +from six import text_type from sqlalchemy.ext.declarative import declarative_base EmeraldHavocBase = declarative_base() metadata = EmeraldHavocBase.metadata def unicode_string(self): - return unicode(self).encode('utf-8') + return text_type(self).encode('utf-8') -EmeraldHavocBase.__str__ == unicode_string +EmeraldHavocBase.__str__ == unicode_string # How to migrate a database diff --git a/gryphon/lib/models/event.py b/gryphon/lib/models/event.py index 18a30ff..5108a7a 100755 --- a/gryphon/lib/models/event.py +++ b/gryphon/lib/models/event.py @@ -4,6 +4,7 @@ import os import uuid +from six import text_type from sqlalchemy import ForeignKey, Column, Integer, Unicode, DateTime, UnicodeText, BigInteger, Numeric from gryphon.lib.models.base import Base @@ -15,30 +16,30 @@ class Event(Base): __tablename__ = 'event' - + unique_id = Column(Unicode(64), nullable=False) event_id = Column(Integer, primary_key=True) time_created = Column(DateTime, nullable=False) exchange_name = Column(Unicode(256), nullable=False) event_type = Column(Unicode(256), nullable=False) data = Column(UnicodeText(length=2**31)) - + def __init__(self, event_type, exchange_name, data): self.time_created = datetime.utcnow() self.event_type = event_type self.exchange_name = exchange_name - self.unique_id = u'evt_%s' % unicode(uuid.uuid4().hex) + self.unique_id = u'evt_%s' % text_type(uuid.uuid4().hex) self.data = json.dumps(data) - + def __unicode__(self): - return unicode(repr(self)) - + return text_type(repr(self)) + def __repr__(self): return json.dumps({ 'event_type':self.event_type, 'exchange':self.exchange_name, 'data': json.loads(self.data), - 'time_created': unicode(self.time_created), + 'time_created': text_type(self.time_created), }, ensure_ascii=False) @@ -48,14 +49,14 @@ class EventRecorder(object): def create(self, db=None, logger=None): self.db = db self.external_logger = logger - + def record(self, event_type, exchange_name='', data={}): event = Event(event_type, exchange_name, data) - + if not hasattr(self, 'db') and not hasattr(self, 'external_logger'): # we didn't call create. we aren't recording events return - + if self.db: self.db.add(event) commit_mysql_session(self.db) @@ -64,6 +65,6 @@ def record(self, event_type, exchange_name='', data={}): else: # we aren't recording events. pass - - + + diff --git a/gryphon/lib/models/exchange.pyx b/gryphon/lib/models/exchange.pyx index 979c7a3..f2a9669 100755 --- a/gryphon/lib/models/exchange.pyx +++ b/gryphon/lib/models/exchange.pyx @@ -102,7 +102,7 @@ class Balance(MutableDict): # Make a deep copy of self. copy.deepcopy() is 4x slower than this # because we know the exact structure and don't have to watch for recursions result = self.__class__() - for currency, m in self.iteritems(): + for currency, m in self.items(): result[currency] = Money(m.amount, m.currency) if isinstance(other, Balance): @@ -117,7 +117,7 @@ class Balance(MutableDict): def __neg__(self): result = self.__class__() - for currency, balance in self.iteritems(): + for currency, balance in self.items(): result[currency] = -balance return result @@ -138,7 +138,7 @@ class Balance(MutableDict): def total_usd_value(self, date=None): total_usd_value = Money(0, 'USD') - for currency, balance in self.iteritems(): + for currency, balance in self.items(): total_usd_value += balance.to('USD', date=date) return total_usd_value diff --git a/gryphon/lib/models/liability.py b/gryphon/lib/models/liability.py index 46494cd..6c7c51d 100755 --- a/gryphon/lib/models/liability.py +++ b/gryphon/lib/models/liability.py @@ -17,6 +17,7 @@ from cdecimal import Decimal from delorean import Delorean +from six import text_type from sqlalchemy import Column, Integer, Unicode, DateTime, UnicodeText, Numeric from gryphon.lib.logger import get_logger @@ -55,7 +56,7 @@ class Liability(Base): _details = Column('details', UnicodeText(length=2**31)) def __init__(self, amount, liability_type, entity_name, time_started=None, time_repayed=None, details=None): - self.unique_id = unicode(uuid.uuid4().hex) + self.unique_id = text_type(uuid.uuid4().hex) self.time_created = datetime.utcnow() self.amount = amount @@ -81,12 +82,12 @@ def to_json(self): return json.dumps({ 'liability_id': self.liability_id, 'unique_id': self.unique_id, - 'time_created': unicode(self.time_created), + 'time_created': text_type(self.time_created), 'amount': self.amount, 'liability_type': self.liability_type, 'entity_name': self.entity_name, - 'time_started': unicode(self.time_started), - 'time_repayed': unicode(self.time_repayed), + 'time_started': text_type(self.time_started), + 'time_repayed': text_type(self.time_repayed), 'details': self.details, }, ensure_ascii=False) diff --git a/gryphon/lib/models/market_data.py b/gryphon/lib/models/market_data.py index bde06ab..4674420 100755 --- a/gryphon/lib/models/market_data.py +++ b/gryphon/lib/models/market_data.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import os -from base import Base +from .base import Base import os import json import uuid from datetime import datetime, timedelta +from six import text_type from sqlalchemy import ForeignKey, Column, Integer, Unicode, DateTime, UnicodeText, Numeric, desc from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base @@ -15,12 +17,12 @@ metadata = Base.metadata class MarketDataRetriever(object): - + BITSTAMP=u'STMP' BTCE=u'BTCE' TRADE = u'TRADE' XBTUSD = u'XBT/USD' - + @staticmethod def trades(exchange=BITSTAMP, ticker_symbol=XBTUSD, start_time=datetime.utcnow()-timedelta(days=30), end_time=datetime.utcnow()): db = session.get_a_gds_db_mysql_session() @@ -31,11 +33,11 @@ def trades(exchange=BITSTAMP, ticker_symbol=XBTUSD, start_time=datetime.utcnow() MarketData.timestamp.between(start_time, end_time)).order_by( desc(MarketData.timestamp)).all() return trades - + def orderbook(self): pass - + class MarketData(Base): @@ -52,7 +54,7 @@ class MarketData(Base): volume = Column('volume', Numeric(precision=20, scale=10)) entry_type = Column(Unicode(32), nullable=True) ticker_symbol = Column(Unicode(256)) - + def __init__(self, timestamp, exchange, price, currency, volume, entry_type, ticker_symbol): self.unique_id = u'mkd_%s' % uuid.uuid4().hex self.time_added = datetime.utcnow() @@ -64,10 +66,10 @@ def __init__(self, timestamp, exchange, price, currency, volume, entry_type, tic self.volume = volume self.entry_type = entry_type self.ticker_symbol = ticker_symbol - + def __str__(self): - return unicode(self) - + return text_type(self) + def __unicode__(self): return '%s,%s,%s,%s,%s,%s,%s' % ( self.timestamp, diff --git a/gryphon/lib/models/orderbook_snapshot.py b/gryphon/lib/models/orderbook_snapshot.py index 3cf607a..96f2e33 100755 --- a/gryphon/lib/models/orderbook_snapshot.py +++ b/gryphon/lib/models/orderbook_snapshot.py @@ -1,31 +1,33 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import import os -from base import Base +from .base import Base import json import uuid from datetime import datetime +from six import text_type from sqlalchemy import ForeignKey, Column, Integer, Unicode, DateTime, UnicodeText, BigInteger, Numeric metadata = Base.metadata class OrderbookSnapshot(Base): __tablename__ = 'orderbook_snapshot' - + unique_id = Column(Unicode(64), nullable=False) orderbook_id = Column(Integer, primary_key=True) data = Column(UnicodeText(length=2**31)) time_retrieved = Column(DateTime, nullable=False) - + def __init__(self, data, time_retrieved): - self.unique_id = u'ord_%s' % unicode(uuid.uuid4().hex) + self.unique_id = u'ord_%s' % text_type(uuid.uuid4().hex) self.time_retrieved = time_retrieved self.data = data - + def __unicode__(self): return u'Orderbook_Snapshot' - + def __repr__(self): return json.dumps({ 'data': self.data, - 'time_retrieved': unicode(self.time_retrieved), + 'time_retrieved': text_type(self.time_retrieved), }, ensure_ascii=False) diff --git a/gryphon/lib/models/ticker.py b/gryphon/lib/models/ticker.py index cd303d7..055fe5a 100755 --- a/gryphon/lib/models/ticker.py +++ b/gryphon/lib/models/ticker.py @@ -4,6 +4,7 @@ import os import uuid +from six import text_type from sqlalchemy import ForeignKey, Column, Integer, Unicode, DateTime, UnicodeText, BigInteger, Numeric from gryphon.lib.models.base import Base @@ -13,25 +14,25 @@ class Ticker(Base): __tablename__ = 'ticker' - + unique_id = Column(Unicode(64), nullable=False) ticker_id = Column(Integer, primary_key=True) exchange = Column(Unicode(256)) data = Column(UnicodeText(length=2**31)) time_retrieved = Column(DateTime, nullable=False) - + def __init__(self, exchange, data): self.time_retrieved = datetime.utcnow() self.exchange = exchange - self.unique_id = u'tkr_%s' % unicode(uuid.uuid4().hex) + self.unique_id = u'tkr_%s' % text_type(uuid.uuid4().hex) self.data = json.dumps(data) - + def __unicode__(self): - return unicode(repr(self)) - + return text_type(repr(self)) + def __repr__(self): return json.dumps({ 'exchange':self.exchange, 'data': self.data, - 'time_retrieved': unicode(self.time_retrieved), + 'time_retrieved': text_type(self.time_retrieved), }, ensure_ascii=False) diff --git a/gryphon/lib/money.py b/gryphon/lib/money.py index 65ff3a8..85fae4d 100755 --- a/gryphon/lib/money.py +++ b/gryphon/lib/money.py @@ -8,6 +8,7 @@ import decimal # need absolute_import from above so that this doesn't load our current file import money as super_money +from six import string_types class Money(super_money.Money): @@ -16,7 +17,7 @@ class Money(super_money.Money): CURRENCIES = FIAT_CURRENCIES + CRYPTO_CURRENCIES def __init__(self, amount="0", currency=None): - if isinstance(amount, basestring): + if isinstance(amount, string_types): amount = amount.replace(",", "") try: diff --git a/gryphon/lib/scrapers/bmo.py b/gryphon/lib/scrapers/bmo.py index a28a9c9..df7a121 100755 --- a/gryphon/lib/scrapers/bmo.py +++ b/gryphon/lib/scrapers/bmo.py @@ -1,3 +1,4 @@ +from __future__ import print_function import logging import os @@ -285,9 +286,9 @@ def __call__(self, driver): def main(): scraper = BMOScraper() - print scraper.load() - print scraper.load_transactions(os.environ['BMO_USD_ACCOUNT_NUMBER']) - print scraper.load_transactions(os.environ['BMO_CAD_ACCOUNT_NUMBER']) + print(scraper.load()) + print(scraper.load_transactions(os.environ['BMO_USD_ACCOUNT_NUMBER'])) + print(scraper.load_transactions(os.environ['BMO_CAD_ACCOUNT_NUMBER'])) scraper.quit() if __name__ == '__main__': diff --git a/gryphon/lib/scrapers/boa.py b/gryphon/lib/scrapers/boa.py index e79dd9e..d819411 100755 --- a/gryphon/lib/scrapers/boa.py +++ b/gryphon/lib/scrapers/boa.py @@ -1,3 +1,4 @@ +from __future__ import print_function import gryphon.lib; gryphon.lib.prepare() import os @@ -82,8 +83,8 @@ def quit(self): def main(): scraper = BoAScraper() - print scraper.load() - print scraper.load_transactions(os.environ['BOA_MAIN_ACCOUNT_NUMBER']) + print(scraper.load()) + print(scraper.load_transactions(os.environ['BOA_MAIN_ACCOUNT_NUMBER'])) scraper.quit() if __name__ == '__main__': diff --git a/gryphon/lib/scripts/bitstamp_auth_test.py b/gryphon/lib/scripts/bitstamp_auth_test.py index 90dfb84..18f8ae7 100755 --- a/gryphon/lib/scripts/bitstamp_auth_test.py +++ b/gryphon/lib/scripts/bitstamp_auth_test.py @@ -2,6 +2,7 @@ This script demonstrates the bitstamp authenticated requests bug that showed up in the week of 26 March. """ +from __future__ import print_function import requests import hmac @@ -12,6 +13,7 @@ import dotenv import os import os.path +from six import text_type dotenv_path = os.path.join(os.path.dirname(__file__), '.env') dotenv.load_dotenv(dotenv_path) @@ -24,7 +26,7 @@ def construct_payload(): - nonce = unicode(int(round(time.time() * 1000))) + nonce = text_type(int(round(time.time() * 1000))) message = nonce + CLIENT_ID + API_KEY sig = hmac.new(SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper() @@ -38,13 +40,13 @@ def construct_payload(): def test_response(response, test_name): - print 'Response: %s' % str(response)[:50] + print('Response: %s' % str(response)[:50]) try: assert('btc_available' in response) - print '%s succeeded!' % test_name + print('%s succeeded!' % test_name) except Exception as e: - print '%s: %s' % (test_name, str(e)) + print('%s: %s' % (test_name, str(e))) def requests_dot_post(): @@ -52,7 +54,7 @@ def requests_dot_post(): This just makes a single request.post call to see if it works. """ - print "Trying requests.post" + print("Trying requests.post") payload = construct_payload() @@ -68,7 +70,7 @@ def session_post(session=None, clear_cookies=None, adaptor=None, cookie_jar=None types. """ if session is None: - print "Trying with a new session" + print("Trying with a new session") session = requests.Session() if adaptor is not None: @@ -77,10 +79,10 @@ def session_post(session=None, clear_cookies=None, adaptor=None, cookie_jar=None if cookie_jar is not None: session.cookies = cookie_jar else: - print "Trying with an extant session" + print("Trying with an extant session") if clear_cookies is True: - print "Clearing the session's cookies" + print("Clearing the session's cookies") session.cookies.clear() payload = construct_payload() @@ -107,15 +109,15 @@ def try_different_adaptors(): tls1 = SSLAdapter(ssl.PROTOCOL_TLSv1) tls11 = SSLAdapter(ssl.PROTOCOL_TLSv1_1) - print 'TLSv1' + print('TLSv1') session = session_post(adaptor=tls1) session_post(session=session) - print 'TLSv1' + print('TLSv1') session = session_post(adaptor=tls11) session_post(session=session) - print 'SSLv3' + print('SSLv3') session = session_post(adaptor=ssl3) session_post(session=session) diff --git a/gryphon/lib/scripts/test_fast_revenue_fees_profit.py b/gryphon/lib/scripts/test_fast_revenue_fees_profit.py index 5308c41..b8cb8f2 100755 --- a/gryphon/lib/scripts/test_fast_revenue_fees_profit.py +++ b/gryphon/lib/scripts/test_fast_revenue_fees_profit.py @@ -2,6 +2,7 @@ Test script for the new fast revenue function. Runs both revenue functions on a random period and checks their results are the same. """ +from __future__ import print_function import pyximport; pyximport.install() @@ -39,7 +40,7 @@ def test_fast_revenue(): for i in range(1, 30): start, end = get_random_period() - print '%s, %s' % (start, end) + print('%s, %s' % (start, end)) slow_revenue = gryphon_profit.revenue_in_period(db, start, end) fast_revenue = gryphon_profit.fast_revenue_in_period(db, start, end) @@ -51,9 +52,9 @@ def test_fast_revenue(): == fast_revenue.round_to_decimal_places(4)) if not result: - print 'BAD: %s, != %s' % (slow_revenue, fast_revenue) + print('BAD: %s, != %s' % (slow_revenue, fast_revenue)) else: - print 'GOOD: %s, == %s' % (slow_revenue, fast_revenue) + print('GOOD: %s, == %s' % (slow_revenue, fast_revenue)) db.remove() @@ -64,7 +65,7 @@ def test_fast_profit(): for i in range(1, 30): start, end = get_random_period() - print '%s, %s' % (start, end) + print('%s, %s' % (start, end)) slow_profit = gryphon_profit.profit_in_period(db, start, end) fast_profit = gryphon_profit.fast_profit_in_period(db, start, end) @@ -73,9 +74,9 @@ def test_fast_profit(): == fast_profit.round_to_decimal_places(4)) if not result: - print 'BAD: %s, != %s' % (slow_profit, fast_profit) + print('BAD: %s, != %s' % (slow_profit, fast_profit)) else: - print 'GOOD: %s, == %s' % (slow_profit, fast_profit) + print('GOOD: %s, == %s' % (slow_profit, fast_profit)) db.remove() @@ -86,7 +87,7 @@ def test_fast_revenue_fees_profit(): for i in range(1, 30): start, end = get_random_period() - print '%s, %s' % (start, end) + print('%s, %s' % (start, end)) slow_revenue, slow_fees, slow_profit = gryphon_profit.revenue_fees_profit_in_period(db, start, end) fast_revenue, fast_fees, fast_profit = gryphon_profit.fast_revenue_fees_profit_in_period(db, start, end) @@ -99,9 +100,9 @@ def test_fast_revenue_fees_profit(): == fast_fees.round_to_decimal_places(4)) if not result: - print 'BAD' + print('BAD') else: - print 'GOOD' + print('GOOD') db.remove() diff --git a/gryphon/lib/util/profile.py b/gryphon/lib/util/profile.py index dac81d1..c948e1f 100755 --- a/gryphon/lib/util/profile.py +++ b/gryphon/lib/util/profile.py @@ -8,11 +8,12 @@ the outputs of each can be different levels of usable for different cases, so I included both here. """ +from __future__ import absolute_import from collections import defaultdict import functools import timeit -import monkeypatch_timeit; monkeypatch_timeit.monkeypatch_timeit() +from . import monkeypatch_timeit; monkeypatch_timeit.monkeypatch_timeit() from line_profiler import LineProfiler def do_profile(follow=[]): diff --git a/gryphon/tests/environment/exchange_coordinator/kraken.py b/gryphon/tests/environment/exchange_coordinator/kraken.py index e5a69d0..c7647b3 100644 --- a/gryphon/tests/environment/exchange_coordinator/kraken.py +++ b/gryphon/tests/environment/exchange_coordinator/kraken.py @@ -2,6 +2,7 @@ """ import pyximport; pyximport.install() import os +import time from gryphon.lib.exchange.kraken_btc_eur import KrakenBTCEURExchange from gryphon.fury.harness.exchange_coordinator import ExchangeCoordinator @@ -45,7 +46,7 @@ def test_order_placement(self): self.db.commit() assert result['success'] is True - order1_exchange_order_id = result['order_id'] + order1_exchange_order_id = result['order_id'] db_order = self.db.query(Order)\ .filter(Order.exchange_order_id == order1_exchange_order_id)\ diff --git a/gryphon/tests/logic/configuration/base_test.py b/gryphon/tests/logic/configuration/base_test.py index 8d41e04..cfc062c 100644 --- a/gryphon/tests/logic/configuration/base_test.py +++ b/gryphon/tests/logic/configuration/base_test.py @@ -52,7 +52,7 @@ def test_parse_list_simple(self): value = 'bitstamp' output = configuration.parse_configurable_as_list(value) - + len(output).should.equal(1) output[0].should.equal('bitstamp') @@ -60,8 +60,8 @@ def test_parse_list_more(self): value = 'bitstamp,coinbase,kraken' output = configuration.parse_configurable_as_list(value) - - len(output).should.equal(3) + + len(output).should.equal(3) output[0].should.equal('bitstamp') output[1].should.equal('coinbase') output[2].should.equal('kraken') @@ -70,16 +70,16 @@ def test_parse_list_simple_trailing_comma(self): value = 'bitstamp,' output = configuration.parse_configurable_as_list(value) - - len(output).should.equal(1) + + len(output).should.equal(1) output[0].should.equal('bitstamp') def test_parse_list_more_trailing_comma(self): value = 'bitstamp,coinbase,kraken,' output = configuration.parse_configurable_as_list(value) - - len(output).should.equal(3) + + len(output).should.equal(3) output[0].should.equal('bitstamp') output[1].should.equal('coinbase') output[2].should.equal('kraken') @@ -88,8 +88,8 @@ def test_parse_list_many_commas(self): value = ',bitstamp,coinbase,,,kraken,,,,' output = configuration.parse_configurable_as_list(value) - - len(output).should.equal(3) + + len(output).should.equal(3) output[0].should.equal('bitstamp') output[1].should.equal('coinbase') output[2].should.equal('kraken') @@ -169,8 +169,8 @@ def test_parse_sections_trivial(self): parsed = configuration.parse_sections(parser) - len(parsed.keys()).should.equal(1) - parsed.keys().should.equal(['strategy']) + len(list(parsed.keys())).should.equal(1) + list(parsed.keys()).should.equal(['strategy']) parsed['strategy'].should.equal({'midpoint': Decimal('0.001')}) def test_parse_sections_simple(self): @@ -178,8 +178,8 @@ def test_parse_sections_simple(self): parsed = configuration.parse_sections(parser) - len(parsed.keys()).should.equal(1) - parsed.keys().should.equal(['strategy']) + len(list(parsed.keys())).should.equal(1) + list(parsed.keys()).should.equal(['strategy']) parsed['strategy']['midpoint'].should.equal(Decimal('0.001')) parsed['strategy']['quote_depth'].should.equal(Money('20', 'BTC')) parsed['strategy']['use_gds'].should.equal(True) @@ -190,8 +190,8 @@ def test_parse_sections_multi_section(self): parsed = configuration.parse_sections(parser) - len(parsed.keys()).should.equal(2) - parsed.keys().should.equal(['platform', 'strategy']) + len(list(parsed.keys())).should.equal(2) + list(parsed.keys()).should.equal(['platform', 'strategy']) parsed['strategy']['tick_sleep'].should.equal(Decimal('1')) parsed['platform']['audit'].should.equal(False) @@ -200,12 +200,12 @@ def test_parse_sections_subsection(self): parsed = configuration.parse_sections(parser) - len(parsed.keys()).should.equal(2) - parsed.keys().should.equal(['platform', 'strategy']) + len(list(parsed.keys())).should.equal(2) + list(parsed.keys()).should.equal(['platform', 'strategy']) parsed['strategy']['tick_sleep'].should.equal(Decimal('1')) parsed['platform']['audit'].should.equal(False) - parsed['strategy']['midpoint_weights'].keys().should.equal([ + list(parsed['strategy']['midpoint_weights'].keys()).should.equal([ 'coinbase_btc_usd', 'bitstamp_btc_usd', ]) @@ -215,5 +215,3 @@ def test_parse_sections_subsection(self): parsed['strategy']['midpoint_weights']['bitstamp_btc_usd']\ .should.equal(Decimal('0.5')) - - diff --git a/gryphon/tests/logic/configuration/execution_config_test.py b/gryphon/tests/logic/configuration/execution_config_test.py index 6df4fc1..4a6f871 100644 --- a/gryphon/tests/logic/configuration/execution_config_test.py +++ b/gryphon/tests/logic/configuration/execution_config_test.py @@ -80,8 +80,8 @@ def test_parse_extra_args(self): parsed = config_helper.parse_extra_strategy_args(extra_args) - assert len(parsed.keys()) == 1 - assert parsed.keys()[0] == 'spread' + assert len(list(parsed.keys())) == 1 + assert list(parsed.keys())[0] == 'spread' assert parsed['spread'] == Decimal('0.01') def test_parse_extra_args_boolean(self): @@ -89,8 +89,8 @@ def test_parse_extra_args_boolean(self): parsed = config_helper.parse_extra_strategy_args(extra_args) - assert len(parsed.keys()) == 1 - assert parsed.keys()[0] == 'market_order' + assert len(list(parsed.keys())) == 1 + assert list(parsed.keys())[0] == 'market_order' assert parsed['market_order'] == True def test_parse_extra_args_complex(self): @@ -103,7 +103,7 @@ def test_parse_extra_args_complex(self): parsed = config_helper.parse_extra_strategy_args(extra_args) - assert len(parsed.keys()) == 4 + assert len(list(parsed.keys())) == 4 assert parsed['spread'] == Decimal('0.1') assert parsed['market_order'] == True assert parsed['exchange'] == 'bitstamp' @@ -150,6 +150,6 @@ def test_standardization_exchanges(self): new_config = config_helper.format_file_config_to_standard(base_config) len(new_config['exchanges']).should.equal(1) - len(new_config['exchanges']['coinbase_btc_usd'].keys()).should.equal(1) + len(list(new_config['exchanges']['coinbase_btc_usd'].keys())).should.equal(1) new_config['exchanges']['coinbase_btc_usd']['fiat_balance_tolerance']\ .should.equal(Money('0.01', 'USD')) diff --git a/setup.py b/setup.py index f17aadc..757c3af 100755 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ def run(self): url='http://www.gryphonframework.org', classifiers=( 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.6', 'Operating System :: OS Independent', 'License :: Other/Proprietary License', ), @@ -58,11 +59,11 @@ def run(self): 'chardet==3.0.4', 'coinbase==1.0.4', 'contextlib2==0.5.5', - 'Cython==0.20.1', + 'Cython==0.29.12', 'decorator==4.3.0', 'Delorean>=1.0.0,<2', 'enum34==1.1.6', - 'futures==3.2.0', + 'futures==3.2.0 ; python_version<"3.0"', 'gryphon-cdecimal==2.3', 'gryphon-money', # Our fork of Python Money. 'gryphon-pusherclient', # Our duplicate of PythonPusherClient. @@ -74,7 +75,8 @@ def run(self): 'MarkupSafe==1.0', 'mock==1.0.1', 'more-itertools>=4.2.0,<5', - 'MySQL-python==1.2.5', + 'MySQL-python==1.2.5 ; python_version<"3.0"', + 'mysql-connector-python ; python_version>="3.0"', 'nose==1.3.7', 'pathlib2==2.3.2', 'pexpect==4.6.0', @@ -94,7 +96,7 @@ def run(self): 'retrying==1.3.3', 'scandir==1.7', 'simplegeneric==0.8.1', - 'six==1.11.0', + 'six==1.12.0', 'sure==1.2.9', 'SQLAlchemy>=1.2.10,<1.3', 'termcolor==1.1.0',