def __init__(self): self.logger = logging.getLogger('root') setup_custom_logger('order', log_level=settings.LOG_LEVEL) self.exe_logger = logging.getLogger('order') self.__reset()
def __connect(self, wsURL): '''Connect to the websocket in a thread.''' self.logger.debug("Starting thread") ssl_defaults = ssl.get_default_verify_paths() sslopt_ca_certs = {'ca_certs': ssl_defaults.cafile} self.ws = websocket.WebSocketApp(wsURL, on_message=self.__on_message, on_close=self.__on_close, on_open=self.__on_open, on_error=self.__on_error, header=self.__get_auth()) setup_custom_logger('websocket', log_level=settings.LOG_LEVEL) self.wst = threading.Thread( target=lambda: self.ws.run_forever(sslopt=sslopt_ca_certs)) self.wst.daemon = True self.wst.start() self.logger.info("Started thread") # Wait for connect before continuing conn_timeout = 5 while (not self.ws.sock or not self.ws.sock.connected ) and conn_timeout and not self._error: sleep(1) conn_timeout -= 1 if not conn_timeout or self._error: self.logger.error("Couldn't connect to WS! Exiting.") self.exit() sys.exit(1)
def __connect(self, wsURL): '''Connect to the websocket in a thread.''' self.logger.debug("Starting thread") ssl_defaults = ssl.get_default_verify_paths() sslopt_ca_certs = {'ca_certs': ssl_defaults.cafile} self.ws = websocket.WebSocketApp(wsURL, on_message=self.__on_message, on_close=self.__on_close, on_open=self.__on_open, on_error=self.__on_error, header=self.__get_auth() ) setup_custom_logger('websocket', log_level=settings.LOG_LEVEL) self.wst = threading.Thread(target=lambda: self.ws.run_forever(sslopt=sslopt_ca_certs)) self.wst.daemon = True self.wst.start() self.logger.info("Started thread") # Wait for connect before continuing conn_timeout = 5 while (not self.ws.sock or not self.ws.sock.connected) and conn_timeout and not self._error: sleep(1) conn_timeout -= 1 if not conn_timeout or self._error: self.logger.error("Couldn't connect to WS! Exiting.") self.exit() sys.exit(1)
def __init__(self) -> None: self.logger = log.setup_custom_logger('fundingbot') self.exchange = ExchangeInterface() self.start_balance = self.exchange.get_margin( )['marginBalance'] / 100000000 self.tick_size = self.exchange.get_instrument()['tickSize'] self.loop_count = 1 self.start_time = datetime.utcnow().isoformat(timespec='seconds') + 'Z' self.last_request = datetime.utcnow() self.limits_exist = False position = self.exchange.get_position()['currentQty'] self.hedge_exists = position != 0 and (abs(position) not in [ settings.POSITION_SIZE_BUY, settings.POSITION_SIZE_SELL ]) self.could_hedge = position == 0 self.cancel_open_orders()
def __connect(self, wsURL): '''Connect to the websocket in a thread.''' self.logger.debug("Starting thread") ssl_defaults = ssl.get_default_verify_paths() sslopt_ca_certs = {'ca_certs': ssl_defaults.cafile} self.ws = websocket.WebSocketApp(wsURL, on_message=self.__on_message, on_close=self.__on_close, on_open=self.__on_open, on_error=self.__on_error, header=self.__get_auth()) setup_custom_logger('websocket', log_level=settings.LOG_LEVEL) self.wst = threading.Thread( target=lambda: self.ws.run_forever(sslopt=sslopt_ca_certs)) self.wst.daemon = True self.wst.start() self.logger.info("Started thread") self.__wait_ws(lambda: self.ws.sock and self.ws.sock.connected)
import traceback import ssl from time import sleep import json import decimal import logging from market_maker.settings import settings from market_maker.auth.APIKeyAuth import generate_expires, generate_signature from market_maker.utils import log from market_maker.utils.math import toNearest from future.utils import iteritems from future.standard_library import hooks with hooks(): # Python 2/3 compat from urllib.parse import urlparse, urlunparse logger = log.setup_custom_logger('root') # Connects to BitMEX websocket for streaming realtime data. # The Marketmaker still interacts with this as if it were a REST Endpoint, but now it can get # much more realtime data without heavily polling the API. # # The Websocket offers a bunch of data as raw properties right on the object. # On connect, it synchronously asks for a push of all this data then returns. # Right after, the MM can start using its data. It will be updated in realtime, so the MM can # poll as often as it wants. class BitMEXWebsocket(): # Don't grow a table larger than this amount. Helps cap memory usage. MAX_TABLE_LEN = 200
import uuid from market_maker.settings import settings from market_maker.states import * from market_maker.utils import log logger = log.setup_custom_logger(f'{uuid.uuid4()}') class MockExchangeInterface: ticker = {'last': 3786.0, 'buy': 3785, 'sell': 3787.0, 'mid': 3787.0} position = { 'avgEntryPrice': 0, 'avgCostPrice': 0, 'currentQty': 0, } orders = [] def remove_filled_orders(self): MockExchangeInterface.orders = list( filter(lambda o: o['ordStatus'] != OrderStates.filled, MockExchangeInterface.orders)) # print(MockExchangeInterface.orders)x return MockExchangeInterface.orders def set_ticker(self, key, valye): MockExchangeInterface.ticker[key] = valye MockExchangeInterface.ticker['buy'] = valye - 1 MockExchangeInterface.ticker['sell'] = valye - 1 MockExchangeInterface.ticker['mid'] = key
from copy import deepcopy import linecache import sys import threading from time import sleep import settings from market_maker.utils.singleton import singleton_data from market_maker.utils import log logger = log.setup_custom_logger('root') execept_logger = log.setup_custom_logger('exception') execute_logger = log.setup_custom_logger('order') class BuyThread(threading.Thread): def __init__(self, custom_strategy): logger.info("[BuyThread][run] __init__") threading.Thread.__init__(self) self.custom_strategy = custom_strategy singleton_data.instance().setAllowSell(False) singleton_data.instance().setBuyThread(True) # default(20.0) * (current_quantity / max_order_quantity) # The maximum value is the default even if the quantity you have now is greater than max_order. # MAX = default(20.0) # The more bulk_net_buy orders, the higher the price. currentQty = self.custom_strategy.exchange.get_currentQty() logger.info("[BuyThread][run] MAX_ORDER_QUENTITY : " + str(settings.MAX_ORDER_QUENTITY))
import atexit import signal from market_maker import bitmex from market_maker.settings import settings from market_maker.utils import log, constants, errors, math # Used for reloading the bot - saves modified times of key files import os watched_files_mtimes = [(f, getmtime(f)) for f in settings.WATCHED_FILES] # # Helpers # logger = log.setup_custom_logger("root") class ExchangeInterface: def __init__(self, dry_run=False): self.dry_run = dry_run if len(sys.argv) > 1: self.symbol = sys.argv[1] else: self.symbol = settings.SYMBOL self.bitmex = bitmex.BitMEX( base_url=settings.BASE_URL, symbol=self.symbol, api_key=settings.API_KEY, api_secret=settings.API_SECRET, order_id_prefix=settings.ORDERID_PREFIX,
import sys from copy import deepcopy from market_maker.market_maker import OrderManager, ExchangeInterface from market_maker.settings import settings from market_maker.utils import log from market_maker.states import * # # Helpers # logger = log.setup_custom_logger('customer') class CustomOrderManager(OrderManager): def __init__(self): self.history_orders = [] self.history_log_message = [] self.log_message = [] self.orders = {} self.orders[OrderSide.sell] = [] self.orders[OrderSide.buy] = [] super().__init__() def order_is_filled(self, order): cl_ord_id = order.get('clOrdID', False) execution = self.exchange.order_by_clOrdID(cl_ord_id) if cl_ord_id and len(execution) > 0: return execution[-1].get('ordStatus') == OrderStates.filled else: return False
import linecache import os import pathlib import sys import threading import settings from telegram.ext import Updater, CommandHandler, MessageHandler, Filters from market_maker.utils import log from market_maker.utils.singleton import singleton_data execept_logger = log.setup_custom_logger('exception') logger = log.setup_custom_logger('root') class Telegram(threading.Thread): def __init__(self, custom_strategy): logger.info("[Telegram] __init__") threading.Thread.__init__(self) self.custom_strategy = custom_strategy self.setApiKey() #self.chat_id = '1653838244' def run(self): """Start the bot.""" logger.info("[telegram][run]") # Create the Updater and pass it your bot's token. # Make sure to set use_context=True to use the new context based callbacks # Post version 12 this will no longer be necessary
import signal import os import math from market_maker import bitmex from market_maker.settings import settings from market_maker.utils import log, constants, errors, botmath # Used for reloading the bot - saves modified times of key files import os watched_files_mtimes = [(f, getmtime(f)) for f in settings.WATCHED_FILES] # # Helpers # logger = log.setup_custom_logger('root') class ExchangeInterface: def __init__(self, dry_run=False): self.dry_run = dry_run if len(sys.argv) > 1: self.symbol = sys.argv[1] else: self.symbol = settings.SYMBOL self.bitmex = bitmex.BitMEX(base_url=settings.BASE_URL, symbol=self.symbol, apiKey=settings.API_KEY, apiSecret=settings.API_SECRET, orderIDPrefix=settings.ORDERID_PREFIX, postOnly=settings.POST_ONLY) def cancel_order(self, order): tickLog = self.get_instrument()['tickLog']
import string import atexit from market_maker import bitmex from market_maker.settings import settings from market_maker.utils import log, constants, errors # Used for reloading the bot - saves modified times of key files import os watched_files_mtimes = [(f, getmtime(f)) for f in settings.WATCHED_FILES] # # Helpers # logger = log.setup_custom_logger('root') class ExchangeInterface: def __init__(self, dry_run=False): self.dry_run = dry_run if len(sys.argv) > 1: self.symbol = sys.argv[1] else: self.symbol = settings.SYMBOL self.bitmex = bitmex.BitMEX(base_url=settings.BASE_URL, symbol=self.symbol, login=settings.LOGIN, password=settings.PASSWORD, otpToken=settings.OTPTOKEN, apiKey=settings.API_KEY, apiSecret=settings.API_SECRET, orderIDPrefix=settings.ORDERID_PREFIX) def authenticate(self): if not self.dry_run:
from datetime import datetime from dateutil import tz import signal import schedule import threading from time import sleep from market_maker.utils import log from bot import FundingBot import settings logger = log.setup_custom_logger('strat') def half_funding(bot: FundingBot) -> None: """4 hours until funding: enter a position if funding is negative, go long if funding is positive, go short """ bot.could_hedge = False bot.exit_position(market=False, wait_for_fill=True) bot.cancel_open_orders() funding_rate = bot.get_funding_rate() logger.info('funding rate: %.4f%%' % (funding_rate * 100))
from market_maker.utils import log, constants, errors, math import time import math as math_lib import threading import numpy as np from decimal import * import pandas as pd import ccxt # Chosing the correct settings file based on the parameter if len(sys.argv) == 1: settings = SettingsDict.OPTIONS['XBTUSD'] else: settings = SettingsDict.OPTIONS[str(sys.argv[1])] logger = log.setup_custom_logger(str(sys.argv[1])) # Used symbols SYMBOLS = ['XBTUSD', 'ETHUSD'] print(settings) from influxdb import InfluxDBClient # Used for reloading the bot - saves modified times of key files import os watched_files_mtimes = [(f, getmtime(f)) for f in settings.WATCHED_FILES] # # Helpers #
from subprocess import run, PIPE, DEVNULL from time import sleep import numpy as np import pytz import pywt from dateutil import parser import talib.stream as ta import get_history_bitmex import globalvar from market_maker import bitmex from market_maker.utils import log import api_keys logger = log.setup_custom_logger('root', log_level='INFO') if not testing: HOST = "https://www.bitmex.com" SPEC_URI = HOST + "/api/explorer/swagger.json" # See full config options at http://bravado.readthedocs.io/en/latest/configuration.html config = { # Don't use models (Python classes) instead of dicts for #/definitions/{models} 'use_models': True, # This library has some issues with nullable fields 'validate_responses': False, # Returns response in 2-tuple of (body, response); if False, will only return body 'also_return_response': False, } API_KEY = api_keys.bmx_api_key
from market_maker.utils import log, errors, constants from market_maker.settings import settings from market_maker.utils.math import toNearest from future.utils import iteritems import atexit import signal from market_maker.exchange_interface import ExchangeInterface from market_maker.tape_interface import Tape import pytz import random import uuid # to generate unique id for linked orders import stockstats import math from market_maker.strategies import funding_rates logger = log.setup_custom_logger(__name__) VERSION = 'v0.2' pd.options.display.width = 300 # for pandas class OrderManager: def __init__(self): self.exchange = ExchangeInterface(settings.DRY_RUN) # Once exchange is created, register exit handler that will always cancel orders on any error. atexit.register(self.exit) signal.signal(signal.SIGTERM, self.exit) logger.info("Using symbol %s." % self.exchange.symbol) # self.start_time = datetime.utcnow() self.instrument = self.exchange.get_instrument() self.starting_qty = self.exchange.get_currentQty() self.running_qty = self.starting_qty
import sys from market_maker.market_maker import OrderManager from market_maker.utils import log, constants, errors, math from market_maker.settings import settings import requests from time import sleep # # Helpers # logger = log.setup_custom_logger('xxx') class CustomOrderManager(OrderManager): def reset(self): # self.exchange.cancel_all_orders() self.sanity_check() self.print_status() # Create orders and converge. self.place_orders() def exit(self): try: # self.exchange.cancel_all_orders() self.exchange.bitmex.exit() except errors.AuthenticationError as e: logger.info("Was not authenticated; could not cancel orders.") except Exception as e:
import signal from market_maker import bitmex from market_maker.settings import settings from market_maker.utils import log, constants, errors # Used for reloading the bot - saves modified times of key files import os watched_files_mtimes = [(f, getmtime(f)) for f in settings.WATCHED_FILES] # # Helpers # logger = log.setup_custom_logger("root") class ExchangeInterface: def __init__(self, dry_run=False): self.dry_run = dry_run if len(sys.argv) > 1: self.symbol = sys.argv[1] else: self.symbol = settings.SYMBOL self.bitmex = bitmex.BitMEX( base_url=settings.BASE_URL, symbol=self.symbol, login=settings.LOGIN, password=settings.PASSWORD, otpToken=settings.OTPTOKEN,