def watch(): db = session.get_a_trading_db_mysql_session() r = session.get_a_redis_connection() logger.info('Reporting for duty.') try: while True: logger.info('Scanning for abnormalities.') check_profit(db) check_open_pl(db) check_ticktimes(db) check_position(db) check_btc_net_assets(db) check_spreads_are_normal(db) check_fv_not_stagnant(db) check_fv_predictor_key_set(r) # for some reason this commit is needed to pick up changes on # subsequent queries. session.commit_mysql_session(db) logger.info('Going to sleep for %s seconds.' % TICK_SLEEP) time.sleep(TICK_SLEEP) finally: db.remove()
def test_fast_revenue_fees_profit(): db = session.get_a_trading_db_mysql_session() for i in range(1, 30): start, end = get_random_period() 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) result = (slow_revenue.round_to_decimal_places(4) == fast_revenue.round_to_decimal_places(4) and slow_profit.round_to_decimal_places(4) == fast_profit.round_to_decimal_places(4) and slow_fees.round_to_decimal_places(4) == fast_fees.round_to_decimal_places(4)) if not result: print 'BAD' else: print 'GOOD' db.remove()
def main(exchanges, execute): exchanges = configuration.parse_configurable_as_list(exchanges) db = session.get_a_trading_db_mysql_session() for exchange_name in exchanges: exchange_wrapper = exchange_factory.make_exchange_from_key( exchange_name) initialize_exchange_ledger(db, exchange_wrapper) if execute is True: db.commit()
def get_target(exchange_name): db = session.get_a_trading_db_mysql_session() try: exchange = make_exchange_from_key(exchange_name) exchange_data = exchange.exchange_account_db_object(db) if not exchange_data: exchange_data = ExchangeData(exchange.name) target = exchange_data.target['BTC'] logger.info("%s's target is %s", exchange.friendly_name, target) finally: db.remove() return target
def __init__(self): tornado.web.Application.__init__(self, url_patterns, **settings) self.dashboard_db = session.get_a_dashboard_db_mysql_session() self.trading_db = session.get_a_trading_db_mysql_session() try: self.gds_db = session.get_a_gds_db_mysql_session() except KeyError as e: logger.info(GDS_ERROR) self.gds_db = None self.configuration = configuration.read_config_from_file( 'dashboards.conf')
def withdraw(exchange_name, target_exchange_name, amount_str): db = session.get_a_trading_db_mysql_session() try: exchange_data = make_exchange_data_from_key(exchange_name, db) target_exchange_data = make_exchange_data_from_key(target_exchange_name, db) target_exchange = make_exchange_from_key(target_exchange_name) amount = Money.loads(amount_str) addr = target_exchange.current_deposit_address exchange_data.record_withdrawal(target_exchange_data, amount, addr) session.commit_mysql_session(db) logger.info(tc.colored("Recorded %s withdrawal from %s" % (amount, exchange_name), "green")) finally: db.remove()
def get_db_balances(exchanges): db = session.get_a_trading_db_mysql_session() db_balances = {} db_balances['system'] = Balance() try: for exchange in exchanges: exchange_data = exchange.exchange_account_db_object(db) db_balances[exchange.name] = exchange_data.balance db_balances['system']['USD'] += db_balances[exchange.name].fiat().to('USD') db_balances['system']['BTC'] += db_balances[exchange.name]['BTC'] finally: db.close() return db_balances
def withdraw_fiat(exchange_name, target_exchange_name, amount_str, deposit_amount_str, transaction_details): db = session.get_a_trading_db_mysql_session() try: exchange_data = make_exchange_data_from_key(exchange_name, db) target_exchange_data = make_exchange_data_from_key(target_exchange_name, db) amount = Money.loads(amount_str) if deposit_amount_str: deposit_amount = Money.loads(deposit_amount_str) exchange_data.record_fiat_withdrawal(target_exchange_data, amount, deposit_amount=deposit_amount, transaction_details=transaction_details) else: exchange_data.record_fiat_withdrawal(target_exchange_data, amount, transaction_details=transaction_details) session.commit_mysql_session(db) logger.info(tc.colored("Recorded %s withdrawal from %s" % (amount, exchange_name), "green")) finally: db.remove()
def transaction_complete(exchange_name, currency): db = session.get_a_trading_db_mysql_session() try: exchange_data = make_exchange_data_from_key(exchange_name, db) tr = db.query(Transaction).filter_by(exchange=exchange_data).filter_by(_amount_currency=currency).filter_by(transaction_status=Transaction.IN_TRANSIT).order_by(Transaction.time_created).first() if tr: tr.complete() session.commit_mysql_session(db) if tr.transaction_type == Transaction.DEPOSIT: action = "deposit to" elif tr.transaction_type == Transaction.WITHDRAWL: action = "withdrawal from" logger.info(tc.colored("Recorded %s %s %s" % (tr.amount, action, exchange_name), "green")) else: logger.info(tc.colored("No Transaction of that currency found", "red")) finally: db.remove()
def run(): db = session.get_a_trading_db_mysql_session() try: logger.info('Reporting for duty.') while True: audit_bmo_accounts(db) audit_boa_accounts(db) session.commit_mysql_session(db) logger.info('Going to sleep for %s.' % humanize_seconds(TICK_SLEEP)) time.sleep(TICK_SLEEP) finally: db.remove()
def run(): db = session.get_a_trading_db_mysql_session() DatumRecorder().create(db=db) logger.info('Reporting for duty.') try: while True: current_time = Delorean().datetime try: update_tx_hashes(db) except Exception as e: logger.exception('Error while updating transaction hashes') # Checking the exact minute amounts works because the shoebox is ticking every 1m # This may not work 100% if the shoebox tick takes any noticable amount of time # to run. In that case we might tick at the end of xx:59 and the beginning of xx:01, # and these tasks wouldn't run. We'll keep an eye on it and may have to add some # persistance later. # every 5 minutes if current_time.minute % 5 == 0: try: get_breaking_bitcoin_news() except Exception: logger.exception('Error while getting breaking news') # every hour if current_time.minute == 0: money_moving() manual_btc_withdrawals(db) # end of day UTC if current_time.hour == 0 and current_time.minute == 0: notify_revenue(db) heartbeat(SHOEBOX_HEARTBEAT_KEY) session.commit_mysql_session(db) logger.info('Going to sleep for %s.' % humanize_seconds(TICK_SLEEP)) time.sleep(TICK_SLEEP) finally: db.remove()
def wind_down(exchange_name, strategy_params, execute=False): db = session.get_a_trading_db_mysql_session() try: strategy = Strategy( make_exchange_from_key(exchange_name), db, debug=False, backtest=False, execute=execute, params=strategy_params, ) harness = Harness(strategy, db) harness.wind_down() finally: session.commit_mysql_session(db) db.remove()
def test_fast_profit(): db = session.get_a_trading_db_mysql_session() for i in range(1, 30): start, end = get_random_period() 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) result = (slow_profit.round_to_decimal_places(4) == fast_profit.round_to_decimal_places(4)) if not result: print 'BAD: %s, != %s' % (slow_profit, fast_profit) else: print 'GOOD: %s, == %s' % (slow_profit, fast_profit) db.remove()
def test_fast_revenue(): db = session.get_a_trading_db_mysql_session() for i in range(1, 30): start, end = get_random_period() 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) # These numbers will be off by tiny fractions due to rounding differences # between python and sql. Four decimal places of precision here (1/100th of # a cent, is good enough. result = (slow_revenue.round_to_decimal_places(4) == fast_revenue.round_to_decimal_places(4)) if not result: print 'BAD: %s, != %s' % (slow_revenue, fast_revenue) else: print 'GOOD: %s, == %s' % (slow_revenue, fast_revenue) db.remove()
def fix_balance_issues_for_exchange(exchange_name, execute=False): db = session.get_a_trading_db_mysql_session() exchange = exchange_factory.make_exchange_from_key(exchange_name) if not exchange: raise Exception('No exchange %s' % exchange_name) exchange_balance = exchange.get_balance() reset_balance_for_exchange_in_currency( db, exchange, exchange_balance, exchange.currency, execute, ) reset_balance_for_exchange_in_currency( db, exchange, exchange_balance, exchange.volume_currency, execute, )
# There's a bizarre bug I haven't had time to investigate whereby if we import # Delorean in order with the rest of the 3rd party libaries, our time_parsing lib # doesn't work. This only happens in the console. Bizarre. from delorean import Delorean logger = get_logger(__name__) NO_GDS_ERROR = """\ Couldn't get a gds session. Probably missing credentials or GDS isn't set up.\ """ # Load the contents of the .env. environment.load_environment_variables() # Create oft-used database objects. trading_db = session.get_a_trading_db_mysql_session() try: gds_db = session.get_a_gds_db_mysql_session() except Exception as e: logger.info(NO_GDS_ERROR) # Create the oft-used exchange connection shortcuts. console_shortcuts = { 'COINBASE_BTC_USD': 'cb', 'BITSTAMP_BTC_USD': 'b', 'BITSTAMP_BTC_EUR': 'be', 'BITSTAMP_BCH_USD': 'bbch', 'BITSTAMP_BCH_EUR': 'bbche', 'BITSTAMP_BCH_BTC': 'bbchb', 'BITSTAMP_ETH_EUR': 'bee',
def manual_accounting(exchange_name, order_id, actor, execute=False): if actor not in EXPECTED_ACTORS: logger.warning(tc.colored(ACTOR_WARNING, color='yellow')) db = session.get_a_trading_db_mysql_session() try: exchange = make_exchange_from_key(exchange_name) exchange_data = make_exchange_data_from_key(exchange_name, db) vol_currency_key = '%s_total' % exchange.volume_currency.lower() try: exchange.cancel_order(order_id) except CancelOrderNotFoundError: pass details = exchange.get_order_details(order_id) unit_price = details['fiat_total'] / details[vol_currency_key].amount try: order = db.query(Order)\ .filter(Order.exchange_order_id == order_id)\ .filter(Order._exchange_name == exchange.name)\ .one() order.time_created = epoch(details['time_created']).naive action = 'Updated' except sqlalchemy.orm.exc.NoResultFound: order = Order( actor, details['type'], details[vol_currency_key], unit_price, exchange, order_id, ) order.time_created = epoch(details['time_created']).naive order.exchange_rate = Money('1', exchange.currency).to('USD').amount action = 'Added' position_change, position_change_no_fees = order.was_eaten(details) old_balance = exchange_data.balance[exchange.volume_currency] for currency_code, position in position_change.iteritems(): exchange_data.position[currency_code] += position exchange_data.balance[currency_code] += position logger.info( 'Order: %s for %.4f @ %.2f', order.order_type, order.volume, order.price, ) for trade in order.trades: logger.info( 'Trade: %s for %.4f @ %.2f', trade.trade_type, trade.volume, trade.price, ) if execute: db.add(order) db.add(exchange_data) session.commit_mysql_session(db) logger.info( tc.colored( '%s order #%s and its %s trade(s)' % (action, order_id, len(details['trades'])), 'green', )) logger.info( tc.colored( 'Updated balance from %s to %s' % (old_balance, exchange_data.balance[exchange.volume_currency]), 'green', )) else: logger.info( tc.colored( 'pass --execute to save this order to the db', 'red', )) finally: db.remove()
def live_run(configuration): strategy_name = configuration['platform']['strategy'] is_builtin_strategy = configuration['platform']['builtin'] execute = configuration['platform']['execute'] logger.info('live_run(%s, %s)' % (strategy_name, execute)) db = session.get_a_trading_db_mysql_session() harness = Harness(db, configuration) strategy_class = get_strategy_class(strategy_name, is_builtin_strategy) strategy = strategy_class(db, harness, configuration['strategy']) strategy.set_up() harness.strategy = strategy if execute: EventRecorder().create(db=db) DatumRecorder().create(db=db) else: EventRecorder().create() DatumRecorder().create() sentry = Sentry(configuration['platform']['sentry']) heartbeat = Heartbeat(configuration['platform']['heartbeat']) try: tick_count = 0 while True: try: tick_start = Delorean().epoch print '\n\n%s' % strategy.name if warm_shutdown_flag: return # This takes us into the finally block. # Initial audit. This is done inside the main loop so that our robust # exception catching kicks in on initial audit failures. if harness.audit is True and tick_count == 0: # We try a fast audit (no wind down) since the bots usually start # from a clean slate. try: harness.full_audit(wind_down=False) except AuditException: logger.info( 'Bot was not cleanly shut down, winding down and auditing', ) harness.full_audit(wind_down=True) # Regular audits. if (harness.audit is True and tick_count > 0 and tick_count % harness.audit_tick == 0): harness.full_audit() else: harness.tick() harness.post_tick(tick_count) tick_profiling.record_tick_data(tick_start, strategy.name) tick_profiling.record_tick_block_data( strategy, tick_count, strategy.name, ) heartbeat.heartbeat(strategy.name) except Exception as e: sentry.captureException() logger.exception( tc.colored( '[%s] %s' % (e.__class__.__name__, e.message), 'red', )) exception_retry_loop(harness, sentry, db) finally: session.commit_mysql_session(db) tick_count += 1 if harness.strategy_complete() is True: break else: gentle_sleep(harness.sleep_time_to_next_tick()) finally: warm_shutdown(harness, db, sentry, execute) session.commit_mysql_session(db) db.remove() if restart_flag: restart()