Beispiel #1
0
    def create_gateway_obj(self, exchange, setting):
        """
        创建gateway对象
        :param exchange: 交易所
        :param setting: 配置信息
        :return: 交易所对象
        """
        if "BITMEX" == exchange:
            # _bitmex 避免和 bitmex 模块重名,所以加下划线区分
            _bitmex = ccxt.bitmex(setting)
            # 设置为测试服务器
            _bitmex.urls["api"] = _bitmex.urls["test"]
            _bitmex.urls["www"] = _bitmex.urls["test"]
            # 引入bitmex官方的对象
            _bitmex.client = bitmex.bitmex(test=True, api_key=setting["apiKey"], api_secret=setting["secret"])
            return _bitmex
        elif "BITMEX_REAL" == exchange:
            # bitmex实盘对象
            # _bitmex 避免和 bitmex 模块重名,所以加下划线区分
            _bitmex = ccxt.bitmex(setting)

            # 引入bitmex官方的对象
            _bitmex.client = bitmex.bitmex(test=False, api_key=setting["apiKey"], api_secret=setting["secret"])
            return _bitmex
        elif "OKEX" == exchange:
            obj_okex = ccxt.okex3()
            return obj_okex
        else:
            pass
 def __init__(self):
     f = open('config.json', 'r', encoding="utf-8")
     config = json.load(f)
     self.logger = log.get_custom_logger(__name__)
     self.product_code = config['productCode']
     self.count = config['count']
     self.period = config['period']
     self.lot = config['lot']
     code = 'XBTUSD' if self.product_code == 'BTC/USD' self.product_code
     self.candle = Candle(code)
     if config['isTest']:
         apiKey = config['test']['key']
         secret = config['test']['secret']
         self.bitmex = ccxt.bitmex({
             'apiKey': apiKey,
             'secret': secret,
         })
         self.bitmex.urls['api'] = self.bitmex.urls['test']
     else:
         apiKey = config['real']['key']
         secret = config['real']['secret']
         self.bitmex = ccxt.bitmex({
             'apiKey': apiKey,
             'secret': secret,
         })
     self.order = Orders(self.bitmex)
Beispiel #3
0
    def _createExchangeObject(self, exchange):
        ''' Depricated ... now instantiating class using "eval" in __init__'''
        if exchange == "Binance":
            exchange = ccxt.binance()
        elif exchange == "Bitfinex":
            exchange = ccxt.bitfinex2()
        elif exchange == "Bitmex":
            exchange = ccxt.bitmex()
        elif exchange == "BitStamp":
            exchange = ccxt.binance()
        elif exchange == "Bittrex":
            exchange = ccxt.binance()
        elif exchange == "Bithumb":
            exchange = ccxt.bithumb()
        elif exchange == "CCTX":
            exchange = ccxt.cctx()
        elif exchange == "GDAX":
            exchange = ccxt.gdax()
        elif exchange == "HitBC":
            exchange = ccxt.hitbc()
        elif exchange == "Huobipro":
            exchange = ccxt.huobipro()
        elif exchange == "Kraken":
            exchange = ccxt.kraken()
        elif exchange == "OKEx":
            exchange = ccxt.okex()
        else:
            raise "Exception ExchangeCCXT::_createExchangeObject - ccxt Exchange not valid"

        return exchange
Beispiel #4
0
    def __init__(self, order_symbol, order_type, apikey, secret, num_buy,
                 num_sell, order_spread, order_profit, order_amonut_buy,
                 order_amonut_sell, exchange):
        self.order_symbol = order_symbol
        self.apiKey = apikey
        self.secret = secret
        self.order_type = order_type
        self.num_buy = num_buy
        self.num_sell = num_sell
        self.order_spread = order_spread
        self.order_profit = order_profit
        self.order_amonut_buy = order_amonut_buy
        self.order_amonut_sell = order_amonut_sell
        if self.order_symbol == 'BTC/USD':
            self._symbol = 'XBTUSD'
        elif self.order_symbol == 'ETH/USD':
            self._symbol = 'ETHUSD'
        else:
            self._symbol = self.order_symbol
        # 初始化交易所
        if exchange == 'bitmex':
            self.exchange = ccxt.bitmex({
                "apiKey": self.apiKey,
                "secret": self.secret
            })

        client = pymongo.MongoClient('localhost', port=27017)  # 连接数据库
        db = client['bitmex']

        self.col = db[self.order_symbol]
Beispiel #5
0
 def __init__(self, exchange, symbol=u'BTC/USD', logfile='full.log'):
     if exchange in self.known_exchanges:
         if exchange == 'bfx':
             self.exchange = ccxt.bitfinex2({
                 'rateLimit': 10000,
                 'enableRateLimit': True
             })
         if exchange == 'bitmex':
             self.exchange = ccxt.bitmex({
                 'rateLimit': 10000,
                 'enableRateLimit': True
             })
         self.symbol = symbol
     self.logger = logging.getLogger(__name__ + '.ExchgData')
     self.logger.setLevel(logging.DEBUG)
     sh = logging.StreamHandler()
     dh = logging.FileHandler(logfile)
     sh.setLevel(logging.INFO)
     dh.setLevel(logging.DEBUG)
     fm = logging.Formatter(
         '[%(asctime)s][%(levelname)s][%(name)s] %(message)s')
     dh.setFormatter(fm)
     sh.setFormatter(fm)
     self.logger.addHandler(sh)
     self.logger.addHandler(dh)
     self.logger.info("Logger initialized")
Beispiel #6
0
    def __init__(self, config: dict, logger=None, client=None):
        self._config = config
        self._logger = logger

        self._symbol = config["symbol"]

        self._ichimoku_tenkan_sen_period = config["ichimoku_tenkan_sen_period"]
        self._ichimoku_kijun_sen_period = config["ichimoku_kijun_sen_period"]
        self._ichimoku_senkou_span_b_period = config[
            "ichimoku_senkou_span_b_period"]
        self._ichimoku_displacement_period = config[
            "ichimoku_displacement_period"]
        self._data_period = config["data_period"]

        self._leverage = config["leverage"]
        self._n_multiplier = config["n_multiplier"]

        self._seconds_per_cycle = config["seconds_per_cycle"]

        if client:
            self._client = client
        else:
            self._client = bitmex({
                "test": config["test"],
                "apiKey": config["apiKey"],
                "secret": config["secret"]
            })
Beispiel #7
0
class MexWrapper(object):

    keys = []
    all_exchanges = []
    client = ccxt.bitmex()

    xbit = "BTC/USD"
    eth = "ETH/USD"

    def __init__(self):
        return

    def get_exchange_markets(self):
        return self.client.load_markets()

    def fetch_and_save_historical_bar_data(self, look_back, time_int):
        lb_date = datetime.now() - timedelta(days=look_back)
        hist = mex.client.fetch_ohlcv(self.xbit, timeframe="1d", since=self.client.parse8601(lb_date.strftime('%Y-%m-%dT%H:%M:%S')))
        df = pd.DataFrame(hist)
        df.columns = ["date", "open", "high", "low", "close", "volume"]
        df["ewma"] = pd
        df.to_csv("../hist_data/mex/" + self.xbit.split("/")[0] + ".txt")
        return df
    def read_data_file(self):
        df = pd.DataFrame().from_csv("../hist_data/mex/" + self.xbit.split("/")[0] + ".txt")
        print(df.head())
def test_connection(bot_id):
    f = open("bitmex_api_credential.yml", "r")
    data = yaml.load(f)
    f.close()
    bitmex = ccxt.bitmex(data["test_net"])
    bitmex.urls["api"] = bitmex.urls["test"]
    return bitmex
Beispiel #9
0
 def __init__(self):
     access = "api"
     if TEST:
         access = "test"
     self.client = ccxt.bitmex(API[access])
     self.client.urls["api"] = self.client.urls[access]
     self.pair = PAIR
Beispiel #10
0
    def __init__(self):
        conf = configs.read()
        api, secret = conf['API_KEY'], conf['API_SECRET']
        self.bitmex = ccxt.bitmex({'apiKey': api, 'secret': secret})
        # self.bitmex.urls['api'] = self.bitmex.urls['test']  # comment if want to trade at mainnet
        self.symbol = 'BTC/USD'
        self.longed = False
        self.shorted = False
        self.timeframe = conf['TIMEFRAME']
        logging.info('Timeframe: {}'.format(self.timeframe))

        # sl
        try:
            self.sl_percent = conf['SL_PERCENT'] / 100
        except Exception:
            self.sl_percent = None

        # tp
        try:
            self.tp_percent = conf['TP_PERCENT'] / 100
        except Exception:
            self.tp_percent = None

        self.RSI_TOP = conf['RSI_TOP']
        self.RSI_BOT = conf['RSI_BOT']
        self.sl_lvl = -1
        self.tp_lvl = -1
        self.leverage = conf['LEVERAGE']
        self.bitmex.private_post_position_leverage(
            {'symbol': 'XBTUSD', 'leverage': self.leverage + 8})  # setup leverage
        self.amount = self.get_amount()
        self.last_minute = -1
        self.date_open = None
        self.price_open = 0
        self.last_price_close = 0
Beispiel #11
0
    def __init__(self):
        #pubnubから取得した約定履歴を保存するリスト
        #self._executions = deque(maxlen=300)
        self._lot = 0.1
        self._product_code = 'BTC/USD'
        #何分足のデータを使うか.初期値は1分足.
        self._candleTerm = "1T"
        #現在のポジション.1ならロング.-1ならショート.0ならポジションなし.
        self._pos = 0
        #API key(自分のキーに書き換える)
        key = "VHppd1wDBRP3gAcyFGnb1A6f"
        secret = "ESffLhyr1SSum1mQ-fiRTlNaK8wtAujeP-MFXLaFYzXimch3"
        self.order = order(key, secret)
        self.next_order_min = datetime.datetime.now()
        self.api = ccxt.bitmex({
        'apiKey' : key,
        'secret' : secret
        })

        #ラインに稼働状況を通知(トークンのキーは適宜書き換える)
        self.line_notify_token = 'fVXGnTYKe6uORVNOJJzwbpqzUwTpPr01YZWkq3H1X7o'
        self.line_notify_api = 'https://notify-api.line.me/api/notify'
        #証拠金
        #self._margin = self.api.getcollateral()
        #注文執行コスト
        self._cost = 0
def Account_Balance(exchange):
    factory = getattr(ccxt, exchange)()
    factory.apiKey = getattr(keychain, exchange).Christian('API')
    factory.secret = getattr(keychain, exchange).Christian('Secret')

    balances = factory.fetch_total_balance()

    usd_Balance = 0
    usdt_usd = ccxt.kraken().fetch_ticker('USDT/USD')['last']
    try:
        btc_usd = ccxt.bitmex().fetch_ticker('BTC/USD')['last']
    except:
        btc_usd = ccxt.coinbase().fetch_ticker('BTC/USD')['last']
    print(btc_usd)

    for currency in balances:
        if balances[currency] != 0:
            time.sleep(0.1)
            if currency == 'BTC':
                balance = balances[currency] * btc_usd
            elif currency == 'USDT':
                balance = balances[currency] * usdt_usd
            else:
                try:
                    btc_pair = factory.fetch_ticker(f'{currency}/BTC')['last']
                    balance = balances[currency] * btc_pair * btc_usd
                except Exception as e:
                    print(e)
            print(currency, balance)
            usd_Balance = usd_Balance + balance

    return [usd_Balance, btc_usd]
Beispiel #13
0
def bitmex():
    bitmex = ccxt.bitmex({
        'apiKey':
        'cY5zFzXgMjHWgJUal5rmUKtg',
        'secret':
        'YjNjCYXWF-B035ecnUyjf7FBDhEuS37vnXxFRE2eyz5cSMsV',
    })
    return bitmex
Beispiel #14
0
 def __init__(self, key, secret):
     self.product_code = 'BTC/USD'
     self.key = key
     self.secret = secret
     self.api = ccxt.bitmex({'apiKey': key, 'secret': secret})
     self.api.urls['api'] = self.api.urls['test']
     #最新の注文リスト
     self.api.fetch_order_book(self.product_code)
Beispiel #15
0
def create_exchanges():
    """
        instantiate the markets
        to include more exchanges use this function.
        new exchanges need to be hand-coded here
    """
    coinbasepro = ccxt.coinbasepro({
        'apiKey': api_keys.coinbasepro['apiKey'],
        'secret': api_keys.coinbasepro['secret'],
    })

    poloniex = ccxt.poloniex({
        'apiKey': api_keys.poloniex['apiKey'],
        'secret': api_keys.poloniex['secret'],
    })

    bittrex = ccxt.bittrex({
        'apiKey': api_keys.bittrex['apiKey'],
        'secret': api_keys.bittrex['secret'],
    })

    binance = ccxt.binance({
        'apiKey': api_keys.binance['apiKey'],
        'secret': api_keys.binance['secret'],
    })

    bitfinex = ccxt.bitfinex({
        'apiKey': api_keys.bitfinex['apiKey'],
        'secret': api_keys.bitfinex['secret'],
    })

    kraken = ccxt.kraken({
        'apiKey': api_keys.kraken['apiKey'],
        'secret': api_keys.kraken['secret'],
    })

    bitmex = ccxt.bitmex({
        'apiKey': api_keys.bitmex['apiKey'],
        'secret': api_keys.bitmex['secret'],
    })

    okex = ccxt.okex({
        'apiKey': api_keys.okex['apiKey'],
        'secret': api_keys.okex['secret'],
    })

    exchanges = [
        coinbasepro, poloniex, bittrex, binance, bitfinex, kraken, bitmex, okex
    ]
    timing_limits = [.35, .35, 1, .35, 2, 1, 1,
                     .35]  # requesting period limit per exchange

    for exchange, timing in zip(exchanges, timing_limits):
        g_storage.timer[exchange.name] = [0, timing]

    # exchanges.pop(exchanges.index(kraken))

    return exchanges
Beispiel #16
0
    def __init__(self, symbol):
        self.ctr = 0
        self.symbol = symbol
        #self.logger = self.setup_logger()

        # hoang: wbFfEOkZqut7OG8rueCPTmEsCsYHyqxakxlg1dNoZbz7EJ6w
        # hoang: ZJ7ZG0bDrem884wQkNnvv2PB

        api_key = "ZJ7ZG0bDrem884wQkNnvv2PB"  #"9FR7reF9F71NDZG_BDoMsfm9" # 8vXVw923QlDRoRtXSwvwbXlU
        api_secret = "wbFfEOkZqut7OG8rueCPTmEsCsYHyqxakxlg1dNoZbz7EJ6w"  #"TiXEEabXxJ_KX5ev_RoOnB-JVQqDdj4AAMJvRBXpPhtAKGVH" # nFZS4qiArohuyY_4J9oGBk49X2iL5LteAXCrHcHveF6j5Gwi

        # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret.
        self.ws = BitMEXWebsocket(endpoint="https://www.bitmex.com/api/v1",
                                  symbol=self.symbol,
                                  api_key=api_key,
                                  api_secret=api_secret)
        self.ws.get_instrument()

        #self.logger.info("Instrument data: %s" % self.ws.get_instrument())
        self.client = bitmex.bitmex(test=False,
                                    api_key=api_key,
                                    api_secret=api_secret)
        self.last_r = None
        self.last_spread = None
        #self.clean = False

        self.tick = []
        self.cur_volatility = None
        self.act_volatility = None
        self.streak = 0
        self.prev_len = 0
        self.cur_len = 0
        self.idle = 0
        self.first = True
        self.sleep_ctr = 0
        self.general_ctr = 0

        exchange = ccxt.bitmex()
        date_N_days_ago = (
            datetime.datetime.now() -
            datetime.timedelta(hours=2)).strftime("%Y-%m-%d %H:%M:%S")
        since = time.mktime(
            datetime.datetime.strptime(date_N_days_ago,
                                       "%Y-%m-%d %H:%M:%S").timetuple()) * 1000
        df = exchange.fetch_ohlcv('ETH/USD',
                                  timeframe='1m',
                                  since=since,
                                  limit=500)
        df = pd.DataFrame(df)
        df.columns = ["Timestamp", "Open", "High", "Low", "tick", "Volume"]

        self.df = pd.DataFrame({'tick': df.tick.values.tolist()})
        #print (df.tail())
        #print (self.df.tail())

        # always fetch df using ccxt
        # check number of pos: if len(pos) > 0 : self.first = False
        logging.info("App Initiated!")
 def create_client(self):
     self.client = ccxt.bitmex({
         'enableRateLimit': True,
         'rateLimit': 3000,
         "apiKey": KEY,
         "secret": SECRET
     })
     #print(dir(self.client))
     self.client.urls['api'] = self.client.urls['test']
Beispiel #18
0
def connection():
    bitmex = ccxt.bitmex()
    bitmex.apiKey = BITMEX_PARAMS['api_key']
    bitmex.secret = BITMEX_PARAMS['SECRET_KEY']
    #区分是否使用了测试连接
    if BITMEX_PARAMS['URL'] == 'test':
        bitmex.urls["api"] = bitmex.urls["test"]
    #print(bitmex.fetch_balance())
    return bitmex
    def __init__(self):
        """

        """
        self.exchange = ccxt.bitmex()
        self.messager = Messenger()
        self.config = {}
        self.config_file = "config.json"
        self.load_config()
        self.fee_rate = 0.002
Beispiel #20
0
    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)

        if settings.DRY_RUN:
            logger.info(
                "Initializing dry run. Orders printed below represent what would be posted to BitMEX."
            )
        else:
            logger.info(
                "Order Manager initializing, connecting to BitMEX. Live run: executing real trades."
            )

        self.start_time = datetime.datetime.now()
        self.instrument = self.exchange.get_instrument()
        self.starting_qty = self.exchange.get_delta()
        self.running_qty = self.starting_qty

        self.cur_volatility = None
        self.act_volatility = None
        self.streak = 0
        self.prev_len = 0
        self.cur_len = 0
        self.idle = 0
        self.first = True
        self.sleep_ctr = 0
        self.general_ctr = 0
        self.ctr = 0
        self.to_record_vola = True

        exchange = ccxt.bitmex()
        logger.info('Connected to CCXT')
        date_N_days_ago = (
            datetime.datetime.now() -
            datetime.timedelta(hours=2)).strftime("%Y-%m-%d %H:%M:%S")
        since = time.mktime(
            datetime.datetime.strptime(date_N_days_ago,
                                       "%Y-%m-%d %H:%M:%S").timetuple()) * 1000
        df = exchange.fetch_ohlcv('ETH/USD',
                                  timeframe='1m',
                                  since=since,
                                  limit=500)
        df = pd.DataFrame(df)
        df.columns = ["Timestamp", "Open", "High", "Low", "tick", "Volume"]

        self.df = pd.DataFrame({'tick': df.tick.values.tolist()})
        logger.info('Retrieved data from CCXT! Len df: {}'.format(len(
            self.df)))

        self.reset()
def connection():  #返会一个CCXT.bitmex类的对象 所有CCXT中关于BITMEX的方法都存在这里面
    bitmex = ccxt.bitmex()
    bitmex.apiKey = BITMEX_PARAMS['api_key']
    bitmex.secret = BITMEX_PARAMS['SECRET_KEY']
    #区分是否使用了测试连接
    if BITMEX_PARAMS['URL'] == 'https://testnet.bitmex.com':
        bitmex.urls["api"] = bitmex.urls["test"]
        print('模拟盘交易')
    else:
        print('实盘交易')
    return bitmex
def init_exchange(exchange):
    params = {
        'apiKey': api_key,
        'secret': api_secret
    }
    if exchange == 'bitmex':
        return ccxt.bitmex(params)
    elif exchange == 'bitfinex':
        return ccxt.bitfinex(params)
    else:
        return
Beispiel #23
0
def bitmex(): #CCXT を呼び出す関数

   bitmex = ccxt.bitmex({
    #APIキーを自分のものに差し替える
    "apiKey": "",
    "secret": ""
       })

   bitmex.urls['api'] = bitmex.urls['test'] #テスト用 本番口座の場合は不要

   return bitmex
Beispiel #24
0
    def get_exchange(self):
        """
        取引所情報を取得する

        :rtype: object
        :return: 取引所情報
        """

        if self.exchange is None:
            self.exchange = ccxt.bitmex()
        return self.exchange
Beispiel #25
0
 def __init__(self):
     super().__init__()
     self.exchanges = {
         "bitmex": {
             "api_key": self.api_key,
             "secret": self.api_secret
         },
     }
     self.bitmex = ccxt.bitmex()
     self.bitmex.apiKey = self.exchanges["bitmex"]["api_key"]
     self.bitmex.secret = self.exchanges["bitmex"]["secret"]
Beispiel #26
0
    def getCandlestick(self, number, period):
        """
        number:ローソク足の数.period:ローソク足の期間(文字列で秒数を指定,Ex:1分足なら"60").cryptowatchはときどきおか
        しなデータ(price=0)が含まれるのでそれを除く.
        """


        timest = ccxt.bitmex().fetch_ticker('BTC/USD')['timestamp']
        timest = timest - number * int(period) * 1000
        time_dic = {"60": "1m", "300":"5m", "3600": "1h"}

        res = ccxt.bitmex().fetch_ohlcv('BTC/USD', timeframe = time_dic[period], since = timest)

        data = []
        for i in res:
            if i[4] != 0:
                column = i[0:5]
                data.append(column)

        return data
Beispiel #27
0
 def __init__(self, g, event_queue, data_handle):
     self.event_queue = event_queue
     self.data_handle = data_handle
     self.g = g
     self.bulks = []
     self.result = []
     self.ex = cxt.bitmex({
         'apiKey': self.g.apiKey,
         'secret': self.g.apiSecret,
         'timeout': 60000,
     })
Beispiel #28
0
 def __init__(self, apiKey, secretKey, trade_amount, leverage, stop):
     self.bitmex = ccxt.bitmex({
         'apiKey': apiKey,
         'secret': secretKey,
         'timeout': 30000,
         'enableRateLimit': True,
     })
     self.symbol = 'BTC/USD'
     self.balance = {'BTC': 0.0, 'USD': 0.0}
     self.trade_amount = trade_amount
     self.leverage = leverage
     self.stop = stop
Beispiel #29
0
 def __init__(self, public_key, secret_key, symbol, jys_name,
              do_it_testnet):
     self.symbol = symbol
     if jys_name == 'bitmex':
         self.agent = ccxt.bitmex()
         if do_it_testnet:
             if 'test' in self.agent.urls:
                 self.agent.urls['api'] = self.agent.urls['test']
             else:
                 Log('Can not translate into bitmex testnet')
         self.agent.apiKey = public_key
         self.agent.secret = secret_key
Beispiel #30
0
 def start(self):
     self.exception = None
     threading.Thread(target=self.timer).start()
     try:
         self.candles = ccxt.bitmex().fetchOHLCV("BTC/USD", '1m', (calendar.timegm(time.gmtime()) - 19 * 60) * 1000, 19)
         self.XBTUSD.run_forever()
     except Exception as e:
         self.exception = e
         file = open('/home/leon/scripts/bitmexWidget.log', 'a')
         file.write(str(self.exception))
         file.close()
         self.tick()
Beispiel #31
0
def get_exchange_list():
    bittrex_exchange = ccxt.bittrex()
    binance_exchange = ccxt.binance()
    kucoin_exchange = ccxt.kucoin()
    huobiPro_exchange = ccxt.huobipro()
    cryptopia_exchange = ccxt.cryptopia()
    bitmex_exchange = ccxt.bitmex()
    list_of_exchanges = [
        bittrex_exchange, binance_exchange, kucoin_exchange, huobiPro_exchange,
        cryptopia_exchange
    ]
    return list_of_exchanges
# -*- coding: utf-8 -*-

import os
import sys
import time

root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root + '/python')

import ccxt  # noqa: E402

bitmex = ccxt.bitmex()

# params:
symbol = 'BTC/USD'
timeframe = '1m'
limit = 100
params = {'partial': False}  # ←--------  no reversal

while True:

    # pay attention to since with respect to limit if you're doing it in a loop
    since = bitmex.milliseconds() - limit * 60 * 1000

    candles = bitmex.fetch_ohlcv(symbol, timeframe, since, limit, params)
    num_candles = len(candles)
    print('{}: O: {} H: {} L:{} C:{}'.format(
        bitmex.iso8601(candles[num_candles - 1][0]),
        candles[num_candles - 1][1],
        candles[num_candles - 1][2],
        candles[num_candles - 1][3],
def get_bitmex_data(symbol, timeframe, length, include_current_candle = True, file_format = ['txt', 'csv'], api_cooldown_seconds = 0):

    """
    Download Crypto OHLCV Data from BitMEX.

    The function fetches OHLCV data via the specified paramteres from the public BitMEX API,
    merges it into a Pandas Data Frame and optionally saves the Data Frame as .txt and/or .csv file.
    Through concatenation more data than specified by the maximal request length of the exchange
    can be fetched.
    Additional timeframes are available (merged from smaller timeframes).

    Parameters
    ----------
    symbol : str
        Symbol of the underlying data, e.g. 'BTC/USD'

    timeframe : str
        Timeframe of the underlying data, e.g. '1h'

    length : int
        Number of Timeframes (Data length), e.g. 500

    include_current_candle : bool
        Include the current, not finished, candle, e.g. True

    file_format : str, list
        Which file format should be used to save the data, e.g. 'csv' or ['txt', 'csv']

    api_cooldown_seconds : int, float
        When fetching a lot of data this allows each request to the API to be made after
        the amount in seconds has passed.
        This prevents possible API errors due to too many requests within a short time.

    Returns
    -------
    Pandas Data Frame and optionally .txt and/or .csv file.
        A table with headers 'Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume' containing the requested data.

    Dependencies
    ------------
    import ccxt
    import time
    import csv
    import pandas as pd

    """

    data_limit = 500 # int(ccxt.bitmex({}).describe()['ratelimit']) returns 2000

    bitmex_symbols = [market['symbol'] for market in ccxt.bitmex({}).fetch_markets()]
    bitmex_timeframes = {'1m': 60*1000, '5m': 5*60*1000, '1h': 60*60*1000, '1d': 24*60*60*1000}
    missing_timeframes = {'3m': ['1m', 3, 1*60*1000], '15m': ['5m', 3, 5*60*1000], '30m': ['5m', 6, 5*60*1000], '2h': ['1h', 2, 60*60*1000], '3h': ['1h', 3, 60*60*1000], '4h': ['1h', 4, 60*60*1000], '6h': ['1h', 6, 60*60*1000], '12h': ['1h', 12, 60*60*1000], '3d': ['1d', 3, 24*60*60*1000], '1w': ['1d', 7, 24*60*60*1000], '2w': ['1d', 14, 24*60*60*1000]}

    timestamp = []
    openx = []
    high = []
    low = []
    close = []
    volume = []

    timestamp_temp = []
    openx_temp = []
    high_temp = []
    low_temp = []
    close_temp = []
    volume_temp = []
    
    proceed = True

    if symbol not in bitmex_symbols:
        print("ERROR:\tPlease use one of the following Symbols:\n\t" + "\n\t".join(sorted(bitmex_symbols)))
        proceed = False

    if not(timeframe in bitmex_timeframes.keys() or timeframe in missing_timeframes.keys()):
        print("ERROR:\tPlease use one of the following Timeframes:\n\tMinute:\t'1m', '3m', '5m', '15m', '30m',\n\tHour:\t'1h', '2h', '3h', '4h', '6h', '12h',\n\tDay:\t'1d', '3d',\n\tWeek:\t'1w', '2w'")
        proceed = False
        
    if not isinstance(length, int) or length < 1:
        print("ERROR:\tPlease use a reasonable number for the argument 'length'.")
        proceed = False

    if type(include_current_candle) != bool:
        print("ERROR:\tPlease use boolean values for argument 'include_current_candle' only.")
        proceed = False
        
    if not(file_format == 'txt' or file_format == 'csv' or file_format == ['txt'] or file_format == ['csv'] or file_format == ['csv', 'txt'] or file_format == ['txt', 'csv'] or
            file_format == '' or file_format == [] or file_format == [''] or file_format == None):
        print("ERROR:\tAllowed values for argument 'file_format' are 'csv', 'txt', ['csv', 'txt'].\n\tIf you do not wish to save the data please use either '', [''], [], None.")
        proceed = False
        
    if file_format == '' or file_format == [] or file_format == [''] or file_format == None:
        file_format = []

    if file_format == 'csv':
        file_format = ['csv']
    if file_format == 'txt':
        file_format = ['txt']

    if not isinstance(api_cooldown_seconds, (int, float)) or api_cooldown_seconds < 0 or api_cooldown_seconds > 60:
        print("ERROR:\tPlease use a reasonable 'api_cooldown_seconds' number of seconds (between 0 and 60).")
        proceed = False
        
    if proceed == True:
        if timeframe in missing_timeframes.keys():
            if include_current_candle == True:
                n_bulk = (length * missing_timeframes[timeframe][1]) // data_limit
                remainder = (length * missing_timeframes[timeframe][1]) % data_limit
            if include_current_candle == False:
                n_bulk = ((length + 1) * missing_timeframes[timeframe][1]) // data_limit
                remainder = ((length + 1) * missing_timeframes[timeframe][1]) % data_limit

            while n_bulk > 0:
                since = round(ccxt.bitmex({}).milliseconds() - (ccxt.bitmex({}).milliseconds() % (missing_timeframes[timeframe][1] * missing_timeframes[timeframe][2])) - (n_bulk * data_limit * missing_timeframes[timeframe][2]) - (remainder * missing_timeframes[timeframe][2]))
                for block in ccxt.bitmex({}).fetch_ohlcv(symbol = symbol, timeframe = missing_timeframes[timeframe][0], since = (since + (missing_timeframes[timeframe][1] * missing_timeframes[timeframe][2])), limit = data_limit):
                    timestamp_temp.append(block[0] - missing_timeframes[timeframe][2])
                    openx_temp.append(block[1])
                    high_temp.append(block[2])
                    low_temp.append(block[3])
                    close_temp.append(block[4])
                    volume_temp.append(block[5])
                n_bulk -= 1
                if n_bulk > 0 or remainder > 0:
                    time.sleep(api_cooldown_seconds)

            if remainder > 0:
                since = round(ccxt.bitmex({}).milliseconds() - (ccxt.bitmex({}).milliseconds() % (missing_timeframes[timeframe][1] * missing_timeframes[timeframe][2])) - (remainder * missing_timeframes[timeframe][2]))
                for block in ccxt.bitmex({}).fetch_ohlcv(symbol = symbol, timeframe = missing_timeframes[timeframe][0], since = (since + (missing_timeframes[timeframe][1] * missing_timeframes[timeframe][2])), limit = remainder + 1):
                    timestamp_temp.append(block[0] - missing_timeframes[timeframe][2])
                    openx_temp.append(block[1])
                    high_temp.append(block[2])
                    low_temp.append(block[3])
                    close_temp.append(block[4])
                    volume_temp.append(block[5])

            if length > 1:
                for i in [num for num in range(1, len(timestamp_temp), missing_timeframes[timeframe][1])][:-1]:
                    timestamp.append(timestamp_temp[i])
                    openx.append(openx_temp[i])
                    high.append(max(high_temp[i:i + missing_timeframes[timeframe][1]]))
                    low.append(min(low_temp[i:i + missing_timeframes[timeframe][1]]))
                    close.append(close_temp[i + (missing_timeframes[timeframe][1] - 1)])
                    volume.append(sum(volume_temp[i:i + missing_timeframes[timeframe][1]]))

                # append all available remaining smaller timeframes to the lists
                timestamp.append(timestamp_temp[i + missing_timeframes[timeframe][1]])
                openx.append(openx_temp[i + missing_timeframes[timeframe][1]])
                high.append(max(high_temp[i + missing_timeframes[timeframe][1]:]))
                low.append(min(low_temp[i + missing_timeframes[timeframe][1]:]))
                close.append(close_temp[-1])
                volume.append(sum(volume_temp[i + missing_timeframes[timeframe][1]:]))

            if length == 1:
                timestamp.append(timestamp_temp[1])
                openx.append(openx_temp[1])
                high.append(max(high_temp[1:]))
                low.append(min(low_temp[1:]))
                close.append(close_temp[-1])
                volume.append(sum(volume_temp[1:]))

        if timeframe not in missing_timeframes.keys():
            if include_current_candle == True:
                n_bulk = length // data_limit
                remainder = length % data_limit
            if include_current_candle == False:
                n_bulk = (length + 1) // data_limit
                remainder = (length + 1) % data_limit

            while n_bulk > 0:
                since = ccxt.bitmex({}).milliseconds() - (n_bulk * data_limit * bitmex_timeframes[timeframe]) - (remainder * bitmex_timeframes[timeframe])
                for block in ccxt.bitmex({}).fetch_ohlcv(symbol = symbol, timeframe = timeframe, since = (since + bitmex_timeframes[timeframe]), limit = data_limit):
                    timestamp.append(block[0] - bitmex_timeframes[timeframe])
                    openx.append(block[1])
                    high.append(block[2])
                    low.append(block[3])
                    close.append(block[4])
                    volume.append(block[5])
                n_bulk -= 1
                if n_bulk > 0 or remainder > 0:
                    time.sleep(api_cooldown_seconds)

            if remainder > 0:
                since = ccxt.bitmex({}).milliseconds() - (remainder * bitmex_timeframes[timeframe])
                for block in ccxt.bitmex({}).fetch_ohlcv(symbol = symbol, timeframe = timeframe, since = (since + bitmex_timeframes[timeframe]), limit = remainder + 1):
                    timestamp.append(block[0] - bitmex_timeframes[timeframe])
                    openx.append(block[1])
                    high.append(block[2])
                    low.append(block[3])
                    close.append(block[4])
                    volume.append(block[5])

        data_identifier = 'bitmex_' + ''.join(symbol.split('/')) + '_' + str(timeframe) + '_' + str(length) + ('_including_current_candle' if include_current_candle == True else '_NOT_including_current_candle')

        if file_format != []:
            for ending in file_format:
                # specify where to save the files e.g.
                #with open('/Users/username/Desktop/' + data_identifier + '.' + str(ending), 'w') as csvfile:
                with open(data_identifier + '.' + str(ending), 'w') as csvfile:
                    writer = csv.writer(csvfile, delimiter = ',', quotechar = '|', quoting = csv.QUOTE_MINIMAL)
                    writer.writerow([head for head in ['Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume']])
                    if include_current_candle == True:
                        write = zip(timestamp, openx, high, low, close, volume)
                    if include_current_candle == False:
                        write = zip(timestamp[:-1], openx[:-1], high[:-1], low[:-1], close[:-1], volume[:-1])
                    for entry in write:
                        writer.writerow(entry)

        if include_current_candle == True:
            df = pd.DataFrame(list(zip(timestamp, openx, high, low, close, volume)), columns = ['Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume'])
            df.name = data_identifier
            return df
        if include_current_candle == False:
            df = pd.DataFrame(list(zip(timestamp[:-1], openx[:-1], high[:-1], low[:-1], close[:-1], volume[:-1])), columns = ['Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume'])
            df.name = data_identifier
            return df