Пример #1
0
def lambda_handler(event, handler):
    binance_api_keys = get_secret()

    curr_date = datetime.date.today().strftime('%Y-%m-%d')
    curr_hour = datetime.datetime.now().strftime('%H')
    TRADE_HOUR = ""
    if curr_hour == "01" or curr_hour == "08" or curr_hour == "16":
        TRADE_HOUR = curr_date + " " + curr_hour + ":17:15"
    elif curr_hour == "23" or curr_hour == "07" or curr_hour == "15":
        curr_hour = str(int(curr_hour) + 1) 
        if len(curr_hour) == 1:
            curr_hour = "0" + curr_hour
        TRADE_HOUR = curr_date + " " + curr_hour + ":00:15"
    else:
        print("Error")

    # time.sleep((datetime.datetime.strptime(TRADE_HOUR, '%Y-%m-%d %H:%M:%S') - datetime.datetime.now()).seconds)

    sub_client = SubscriptionClient(api_key=binance_api_keys["key"], secret_key=binance_api_keys["secret"])

    sub_client.subscribe_mark_price_event("vetusdt", callback, error)

    while running:
        pass

    return "OK"
Пример #2
0
    def __init__(self, requests_only=False):
        super().__init__()

        if not requests_only:
            self.sub_client = SubscriptionClient(api_key=self.api_key,
                                                 secret_key=self.api_secret)
        self.request_client = RequestClient(api_key=self.api_key,
                                            secret_key=self.api_secret)
Пример #3
0
    def __init__(self, settings, logger, on_tick_callback=None):
        super().__init__(settings, logger, on_tick_callback)
        self.symbol = settings.SYMBOL
        self.client = RequestClient(api_key=settings.API_KEY,
                                    secret_key=settings.API_SECRET)
        self.ws = SubscriptionClient(api_key=settings.API_KEY,
                                     secret_key=settings.API_SECRET)

        self.orders = {}
        self.positions = {}
        self.candles: List[Candlestick] = []
        self.last = 0
        self.open = False
        self.listen_key = ""
        self.init()
Пример #4
0
    def __init__(self, settings, logger, on_tick_callback=None):
        super().__init__(settings, logger, on_tick_callback)
        self.symbol: str = settings.SYMBOL
        self.client = RequestClient(api_key=settings.API_KEY,
                                    secret_key=settings.API_SECRET)
        self.ws = SubscriptionClient(api_key=settings.API_KEY,
                                     secret_key=settings.API_SECRET)

        # for binance the key is the internal id (not the exchange id) cause we can't update order but have to cancel and reopen with same id.
        # that leads to different exchange id, but we need to know its the same.
        self.orders = {}
        self.positions = {}
        self.symbol_object: Symbol = None
        self.candles: List[Candlestick] = []
        self.last = 0
        self.open = False
        self.listen_key = ""
        self.lastUserDataKeep = None
        self.wantedResponses = 0  # needed to wait for realtime
        self.init()
Пример #5
0
class Futures(BinanceAPI):

    markPrice = None

    def __init__(self, requests_only=False):
        super().__init__()

        if not requests_only:
            self.sub_client = SubscriptionClient(api_key=self.api_key,
                                                 secret_key=self.api_secret)
        self.request_client = RequestClient(api_key=self.api_key,
                                            secret_key=self.api_secret)

    def callback(self, data_type: 'SubscribeMessageType', event: 'any'):
        if data_type == SubscribeMessageType.RESPONSE:
            print("Event ID: ", event)
        elif data_type == SubscribeMessageType.PAYLOAD:
            self.markPrice = event.markPrice
        else:
            print("Unknown Data:")

    def error(self, e: 'BinanceApiException'):
        return e.error_code + e.error_message

    def start_listening(self, ticker="btcusdt"):
        self.sub_client.subscribe_mark_price_event(ticker, self.callback,
                                                   self.error)

    def stop_listening(self):
        self.sub_client.unsubscribe_all()

    def get_price(self, ticker="btcusdt"):
        try:
            return self.request_client.get_mark_price(symbol=ticker).markPrice
        except BinanceApiException as e:
            return "Invalid symbol." if e.error_code == "ExecuteError" else e.error_message
Пример #6
0

DATA_FILENAME = 'btcusdt_candles.json'
from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

api_key = 'YOUR_API_KEY_HERE'
api_secret = 'YOUR_API_SECRET_HERE'

sub_client = SubscriptionClient(api_key=api_key, secret_key=api_secret)
request_client = RequestClient(api_key=api_key, secret_key=api_secret)

### PARAMETERS ###
# symbol to trade
symbol = 'ETCUSDT'
# order quantity
order_quantity = 7.77
# states
IDLE = 0
INVESTED = 1
state = IDLE

# cooldown time between last sell
wait_time = 5 * 1000
# last sell cooldown flag
Пример #7
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-client")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintBasic.print_obj(event)
        #sub_client.unsubscribe_all()
    else:
        print("Unknown Data:")
    print()


def error(e: 'BinanceApiException'):
    print(e.error_code + e.error_message)
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintBasic.print_obj(event)
    else:
        print("Unknown Data:")
    print()


def error(e: 'BinanceApiException'):
    print(e.error_code + e.error_message)
Пример #9
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintBasic.print_obj(event)
    else:
        print("Unknown Data:")
    print()


def error(e: 'BinanceApiException'):
    print(e.error_code + e.error_message)
Пример #10
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        pass
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintMix.print_data(event.bids)
        PrintMix.print_data(event.asks)
        sub_client.unsubscribe_all()


def error(e: 'BinanceApiException'):
    pass

import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        print("Event type: ", event.eventType)
        print("Event time: ", event.eventTime)
        print("Symbol: ", event.symbol)
        print("Data:")
        PrintBasic.print_obj(event.data)
        sub_client.unsubscribe_all()
    else:
        print("Unknown Data:")
    print()
Пример #12
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintBasic.print_obj(event)
    else:
        print("Unknown Data:")
    print()


def error(e: 'BinanceApiException'):
    print(e.error_code + e.error_message)
Пример #13
0
    the_logger = logging.getLogger(log_id)
    the_logger.setLevel(logging.INFO)
    handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter(
        "%(asctime)s [%(levelname)-5.5s]  %(message)s")
    handler.setFormatter(formatter)
    the_logger.addHandler(handler)


setup_logger("user-data-stream")
setup_logger("binance-futures")
setup_logger("binance-client")

my_logger = logging.getLogger("user-data-stream")

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def simple_cb(data_type: SubscribeMessageType, event: 'any', msg):
    if data_type == SubscribeMessageType.PAYLOAD:
        my_logger.info(msg)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        if (event.eventType == "ACCOUNT_CONFIG_UPDATE"):
            print("Event Type: ", event.eventType)
            print("Event time: ", event.eventTime)
            print("Transaction time: ", event.transactionTime)
Пример #14
0
result = request_client.keep_user_data_stream()
print("Result: ", result)

# Close user data stream
# result = request_client.close_user_data_stream()
# print("Result: ", result)

logger = logging.getLogger("binance-client")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(
    api_key="vB5t62MtpTHQLEDBydDLoQ5rtif4UDByVBi0Js1kkcHucdzNPsg1YWdomp0W489W",
    secret_key=
    "KxgT9wHCR03ctg7hS9B48J3l21s7Le6n5KOco9smvFPNasNvDZxtsOi8tfilQ1AH")


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        if (event.eventType == "ACCOUNT_UPDATE"):
            print("Event Type: ", event.eventType)
            print("Event time: ", event.eventTime)
            print("Transaction time: ", event.transactionTime)
            print("=== Balances ===")
            PrintMix.print_data(event.balances)
            print("================")
            print("=== Positions ===")
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        print("Event type: ", event.eventType)
        print("Event time: ", event.eventTime)
        print("Symbol: ", event.symbol)
        print("Data:")
        PrintBasic.print_obj(event.data)
        sub_client.unsubscribe_all()
    else:
        print("Unknown Data:")
    print()
Пример #16
0
def profit_order_start(user_info):
    """
    user_info:api_lable, tg_id, b_api_key, b_secret_key, tg_token
    启动单线程的数据订阅
    """
    # TODO 查询当前持仓
    # 创建当前持仓列表,记录交易对,持仓方向,
    def callback(data_type: 'SubscribeMessageType', event: 'any'):
        if data_type == SubscribeMessageType.RESPONSE:
            print("Event ID: ", event)
        elif data_type == SubscribeMessageType.PAYLOAD:
            if (event.eventType == "ACCOUNT_UPDATE"):
                print("Event Type: ", event.eventType)
                print("Event time: ", event.eventTime)
                print("Transaction time: ", event.transactionTime)
                print("=== Balances ===")
                PrintMix.print_data(event.balances)
                balance_str = ""
                for user_balance in event.balances:
                    asset = user_balance.asset  # 交易对
                    walletBalance = user_balance.walletBalance  # 余额
                    balance_str += "{} {}\n".format(walletBalance, asset)
                balance_str = "账户:{}\n".format(user_info[0]) + balance_str
                # 账户余额变化提醒
                # tg_bot_send_text(balance_str, user_info[1], user_info[4])
                print("================")
                print("=== Positions ===")
                PrintMix.print_data(event.positions)
                print("================")
            elif (event.eventType == "ORDER_TRADE_UPDATE"):
                symbol = event.symbol  # 交易对
                order_id = event.orderId  # 订单ID
                order_type = event.type  # 订单类型
                side = event.side  # 订单方向

                # -----------------------------------------------------------
                origQty = event.origQty  # 订单原始数量
                price = event.price  # 订单原始价格
                # -----------------------------------------------------------
                avgPrice = event.avgPrice  # 订单平均价格
                # ------------------------------------------------------------
                cumulativeFilledQty = event.cumulativeFilledQty  # 订单累计成交量
                lastFilledPrice = event.lastFilledPrice  # 订单末次成交价
                # -----------------------------------------------------------

                executionType = event.executionType  # 本次事件的执行类型
                orderStatus = event.orderStatus  # 订单当前状态
                isMarkerSide = event.isMarkerSide  # 该成交是否为挂单成交
                positionSide = event.positionSide  # 持仓方向

                commissionAsset = event.commissionAsset  # 手续费资产类型
                commissionAmount = event.commissionAmount  # 手续费数量
                bidsNotional = event.bidsNotional  # 买单净值
                asksNotional = event.asksNotional  # 卖单净值
                orderProfit = event.orderProfit  # 该交易实现盈亏

                tz = pytz.timezone('Asia/ShangHai')
                dt = pytz.datetime.datetime.fromtimestamp(event.orderTradeTime / 1000, tz)
                dt.strftime('%Y-%m-%d %H:%M:%S')
                orderTradeTime = str(dt)[:-10]  # 成交时间
                if float(orderProfit) > 0:
                    send_str = "账户:{}\n" \
                               "交易对:{}\n" \
                               "订单号:{}\n" \
                               "订单状态:订单完结\n" \
                               "持仓量:{} {}\n" \
                               "持仓均价:{} USDT\n" \
                               "价值:{:.5f} USDT\n" \
                               "手续费:{} {}\n" \
                               "本单盈亏:{} USDT %f0%9f%92%b0%f0%9f%92%b0%f0%9f%92%b0\n" \
                               "成交时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                cumulativeFilledQty, symbol.replace("USDT", ""), avgPrice,
                                                symbol.replace("USDT", ""),
                                                float(origQty) * float(avgPrice), commissionAmount, commissionAsset,
                                                orderProfit, orderTradeTime)
                    tg_bot_send_text(send_str, user_info[1], user_info[4])
                elif float(orderProfit) < 0:
                    send_str = "账户:{}\n" \
                               "交易对:{}\n" \
                               "订单号:{}\n" \
                               "订单状态:订单完结\n" \
                               "持仓量:{} {}\n" \
                               "持仓均价:{} USDT\n" \
                               "价值:{:.5f} USDT\n" \
                               "手续费:{} {}\n" \
                               "本单盈亏:{} USDT %f0%9f%a5%ba%f0%9f%a5%ba%f0%9f%a5%ba\n" \
                               "成交时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                cumulativeFilledQty, symbol.replace("USDT", ""), avgPrice,
                                                symbol.replace("USDT", ""),
                                                float(origQty) * float(avgPrice), commissionAmount, commissionAsset,
                                                orderProfit, orderTradeTime)
                    tg_bot_send_text(send_str, user_info[1], user_info[4])
                # ======================================================================================================
                if not event.activationPrice is None:
                    print("Activation Price for Trailing Stop: ", event.activationPrice)
                if not event.callbackRate is None:
                    print("Callback Rate for Trailing Stop: ", event.callbackRate)
            elif (event.eventType == "listenKeyExpired"):
                print("Event: ", event.eventType)
                print("Event time: ", event.eventTime)
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
        else:
            print("Unknown Data:")

    def error(e: 'BinanceApiException'):
        print(e.error_code + e.error_message)

    # Start user data stream
    request_client = RequestClient(api_key=user_info[2], secret_key=user_info[3])
    listen_key = request_client.start_user_data_stream()
    print("listenKey: ", listen_key)

    # Keep user data stream
    result = request_client.keep_user_data_stream()
    print("Result: ", result)

    # Close user data stream
    # result = request_client.close_user_data_stream()
    # print("Result: ", result)

    sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)

    sub_client.subscribe_user_data_event(listen_key, callback, error)
Пример #17
0
def all_order_start(user_info):
    """
    user_info:api_lable, tg_id, b_api_key, b_secret_key, tg_token
    启动单线程的数据订阅
    """
    # TODO 查询当前持仓
    # 创建当前持仓列表,记录交易对,持仓方向,
    def callback(data_type: 'SubscribeMessageType', event: 'any'):
        if data_type == SubscribeMessageType.RESPONSE:
            print("Event ID: ", event)
        elif data_type == SubscribeMessageType.PAYLOAD:
            if (event.eventType == "ACCOUNT_UPDATE"):
                print("Event Type: ", event.eventType)
                print("Event time: ", event.eventTime)
                print("Transaction time: ", event.transactionTime)
                print("=== Balances ===")
                PrintMix.print_data(event.balances)
                balance_str = ""
                for user_balance in event.balances:
                    asset = user_balance.asset  # 交易对
                    walletBalance = user_balance.walletBalance  # 余额
                    balance_str += "{} {}\n".format(walletBalance, asset)
                balance_str = "账户:{}\n".format(user_info[0]) + balance_str
                # 账户余额变化提醒
                # tg_bot_send_text(balance_str, user_info[1], user_info[4])
                print("================")
                print("=== Positions ===")
                PrintMix.print_data(event.positions)
                print("================")
            elif (event.eventType == "ORDER_TRADE_UPDATE"):
                print("Event Type: ", event.eventType)
                print("Event time: ", event.eventTime)
                print("Transaction Time: ", event.transactionTime)
                print("Symbol: ", event.symbol)
                print("Client Order Id: ", event.clientOrderId)
                print("Side: ", event.side)
                print("Order Type: ", event.type)
                print("Time in Force: ", event.timeInForce)
                print("Original Quantity: ", event.origQty)
                print("Position Side: ", event.positionSide)
                print("Price: ", event.price)
                print("Average Price: ", event.avgPrice)
                print("Stop Price: ", event.stopPrice)
                print("Execution Type: ", event.executionType)
                print("Order Status: ", event.orderStatus)
                print("Order Id: ", event.orderId)
                print("Order Last Filled Quantity: ", event.lastFilledQty)
                print("Order Filled Accumulated Quantity: ", event.cumulativeFilledQty)
                print("Last Filled Price: ", event.lastFilledPrice)
                print("Commission Asset: ", event.commissionAsset)
                print("Commissions: ", event.commissionAmount)
                print("Order Trade Time: ", event.orderTradeTime)
                print("Trade Id: ", event.tradeID)
                print("Bids Notional: ", event.bidsNotional)
                print("Ask Notional: ", event.asksNotional)
                print("Is this trade the maker side?: ", event.isMarkerSide)
                print("Is this reduce only: ", event.isReduceOnly)
                print("stop price working type: ", event.workingType)
                print("Is this Close-All: ", event.isClosePosition)
                print("========Orders=========")
                # order_str = "交易对:{}\n订单方向:{}\n订单类型:{}\n订单原始数量:{}\n订单原始价格:{}\n订单平均价格:{}\n" \
                #             "条件订单触发价格,对追踪止损单无效:{}\n本次事件的具体执行类型:{}\n订单的当前状态:{}\n订单ID:{}\n" \
                #             "订单末次成交量:{}\n订单累计已成交量:{}\n订单末次成交价格:{}\n手续费资产类型:{}\n手续费数量:{}\n" \
                #             "成交时间:{}\n该成交是作为挂单成交吗?:{}\n是否是只减仓单:{}\n触发价类型:{}\n原始订单类型:{}\n" \
                #             "持仓方向:{}\n该交易实现盈亏:{}".format(
                #     event.symbol, event.side, event.type, event.origQty,
                #     event.price, event.avgPrice, event.stopPrice, event.executionType, event.orderStatus, event.orderId,
                #     event.lastFilledQty, event.cumulativeFilledQty, event.lastFilledPrice, event.commissionAsset,
                #     event.commissionAmount, event.orderTradeTime, event.isMarkerSide, event.isReduceOnly,
                #     event.workingType, event.initOrderStatus, event.positionSide, event.orderProfit
                # )
                symbol = event.symbol  # 交易对
                order_id = event.orderId  # 订单ID
                order_type = event.type  # 订单类型
                side = event.side  # 订单方向

                # -----------------------------------------------------------
                origQty = event.origQty  # 订单原始数量
                price = event.price  # 订单原始价格
                # -----------------------------------------------------------
                avgPrice = event.avgPrice  # 订单平均价格
                # ------------------------------------------------------------
                cumulativeFilledQty = event.cumulativeFilledQty  # 订单累计成交量
                lastFilledPrice = event.lastFilledPrice  # 订单末次成交价
                # -----------------------------------------------------------

                executionType = event.executionType  # 本次事件的执行类型
                orderStatus = event.orderStatus  # 订单当前状态
                isMarkerSide = event.isMarkerSide  # 该成交是否为挂单成交
                positionSide = event.positionSide  # 持仓方向

                commissionAsset = event.commissionAsset  # 手续费资产类型
                commissionAmount = event.commissionAmount  # 手续费数量
                bidsNotional = event.bidsNotional  # 买单净值
                asksNotional = event.asksNotional  # 卖单净值
                orderProfit = event.orderProfit  # 该交易实现盈亏

                tz = pytz.timezone('Asia/ShangHai')
                dt = pytz.datetime.datetime.fromtimestamp(event.orderTradeTime / 1000, tz)
                dt.strftime('%Y-%m-%d %H:%M:%S')
                orderTradeTime = str(dt)[:-10]  # 成交时间

                # 创建/取消订单
                if (orderStatus == "NEW" or orderStatus == "CANCELED") and not isMarkerSide:
                    if orderStatus == "NEW":

                        send_str = "账户:{}\n" \
                                   "交易对:{}\n" \
                                   "订单号:{}\n" \
                                   "订单状态:创建委托订单\n" \
                                   "数量:{} {}\n" \
                                   "平均价格:{} USDT\n" \
                                   "价值:{:.5f} USDT\n" \
                                   "下单时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                    origQty, symbol.replace("USDT", ""),
                                                    price, float(origQty) * float(price), orderTradeTime)
                        tg_bot_send_text(send_str, user_info[1], user_info[4])
                    else:
                        send_str = "账户:{}\n" \
                                   "交易对:{}\n" \
                                   "订单号:{}\n" \
                                   "订单状态:取消委托订单\n" \
                                   "数量:{} {}\n" \
                                   "平均价格:{} USDT\n" \
                                   "价值:{:.5f} USDT\n" \
                                   "取消时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                    origQty, symbol.replace("USDT", ""),
                                                    price, float(origQty) * float(price), orderTradeTime)
                        tg_bot_send_text(send_str, user_info[1], user_info[4])
                elif (orderStatus == "PARTIALLY_FILLED" or orderStatus == "FILLED") and executionType == "TRADE":
                    if float(orderProfit) > 0:
                        send_str = "账户:{}\n" \
                                   "交易对:{}\n" \
                                   "订单号:{}\n" \
                                   "订单状态:订单完结\n" \
                                   "持仓量:{} {}\n" \
                                   "持仓均价:{} USDT\n" \
                                   "价值:{:.5f} USDT\n" \
                                   "手续费:{} {}\n" \
                                   "本单盈亏:{} USDT %f0%9f%92%b0%f0%9f%92%b0%f0%9f%92%b0\n" \
                                   "成交时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                    cumulativeFilledQty, symbol.replace("USDT", ""), avgPrice,
                                                    symbol.replace("USDT", ""),
                                                    float(origQty) * float(avgPrice), commissionAmount, commissionAsset,
                                                    orderProfit, orderTradeTime)
                        tg_bot_send_text(send_str, user_info[1], user_info[4])
                    elif float(orderProfit) < 0:
                        send_str = "账户:{}\n" \
                                   "交易对:{}\n" \
                                   "订单号:{}\n" \
                                   "订单状态:订单完结\n" \
                                   "持仓量:{} {}\n" \
                                   "持仓均价:{} USDT\n" \
                                   "价值:{:.5f} USDT\n" \
                                   "手续费:{} {}\n" \
                                   "本单盈亏:{} USDT %f0%9f%a5%ba%f0%9f%a5%ba%f0%9f%a5%ba\n" \
                                   "成交时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                    cumulativeFilledQty, symbol.replace("USDT", ""), avgPrice,
                                                    symbol.replace("USDT", ""),
                                                    float(origQty) * float(avgPrice), commissionAmount, commissionAsset,
                                                    orderProfit, orderTradeTime)
                        tg_bot_send_text(send_str, user_info[1], user_info[4])
                    else:
                        send_str = "账户:{}\n" \
                                   "交易对:{}\n" \
                                   "订单号:{}\n" \
                                   "订单状态:订单成交\n" \
                                   "成交量:{} {}\n" \
                                   "成交均价:{} USDT\n" \
                                   "价值:{:.5f} USDT\n" \
                                   "手续费:{} {}\n" \
                                   "成交时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                                                    cumulativeFilledQty, symbol.replace("USDT", ""), avgPrice,
                                                    symbol.replace("USDT", ""),
                                                    float(origQty) * float(avgPrice), commissionAmount, commissionAsset,
                                                    orderTradeTime)
                        tg_bot_send_text(send_str, user_info[1], user_info[4])
                # else:
                #     send_str = "账户:{}\n" \
                #                "交易对:{}\n" \
                #                "订单号:{}\n" \
                #                "订单状态:取消委托订单\n" \
                #                "数量:{} {}\n" \
                #                "平均价格:{} USDT\n" \
                #                "价值:{:.5f} USDT\n" \
                #                "取消时间:{}".format(user_info[0], symbol.replace("USDT", "_USDT"), order_id,
                #                                 origQty, symbol.replace("USDT", ""),
                #                                 price, float(origQty) * float(price), orderTradeTime)
                #     tg_bot_send_text(send_str, user_info[1], user_info[4])
                # ======================================================================================================
                # tg_bot_send_text(order_str, user_info[1], user_info[4])
                # ======================================================================================================
                if not event.activationPrice is None:
                    print("Activation Price for Trailing Stop: ", event.activationPrice)
                if not event.callbackRate is None:
                    print("Callback Rate for Trailing Stop: ", event.callbackRate)
            elif (event.eventType == "listenKeyExpired"):
                print("Event: ", event.eventType)
                print("Event time: ", event.eventTime)
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
                print("CAUTION: YOUR LISTEN-KEY HAS BEEN EXPIRED!!!")
        else:
            print("Unknown Data:")

    def error(e: 'BinanceApiException'):
        print(e.error_code + e.error_message)

    # Start user data stream
    request_client = RequestClient(api_key=user_info[2], secret_key=user_info[3])
    listen_key = request_client.start_user_data_stream()
    print("listenKey: ", listen_key)

    # Keep user data stream
    result = request_client.keep_user_data_stream()
    print("Result: ", result)

    # Close user data stream
    # result = request_client.close_user_data_stream()
    # print("Result: ", result)

    sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)

    sub_client.subscribe_user_data_event(listen_key, callback, error)
Пример #18
0
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(
    api_key='EvNt6yBQPge3oq5VX83mOGjwiGx3kzz9jPNMWlDlziSrZ2hLtdfvdIJWOX8Lika5',
    secret_key=
    'qEixH9AQI4jkLIkVpQB7aUInmQDtLkzfnozUMyC8t7Hws57JZZTa3mtkCqzKXXRm')


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        print("Event type: ", event.eventType)
        print("Event time: ", event.eventTime)
        print("transaction time: ", event.transactionTime)
        print("Symbol: ", event.symbol)
        print("first update Id from last stream: ", event.firstUpdateId)
        print("last update Id from last stream: ", event.lastUpdateId)
        print("last update Id in last stream: ",
              event.lastUpdateIdInlastStream)
result = request_client.keep_user_data_stream()
print("Result: ", result)

# Close user data stream
# result = request_client.close_user_data_stream()
# print("Result: ", result)

logger = logging.getLogger("binance-client")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: "SubscribeMessageType", event: "any"):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        if event.eventType == "ACCOUNT_UPDATE":
            print("Event Type: ", event.eventType)
            print("Event time: ", event.eventTime)
            print("Transaction time: ", event.transactionTime)
            print("=== Balances ===")
            PrintMix.print_data(event.balances)
            print("================")
            print("=== Positions ===")
            PrintMix.print_data(event.positions)
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        pass
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintBasic.print_obj(event)


def error(e: 'BinanceApiException'):
    pass


sub_client.subscribe_all_bookticker_event(callback, error)
Пример #21
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        pass
    elif data_type == SubscribeMessageType.PAYLOAD:
        PrintMix.print_data(event.bids)
        PrintMix.print_data(event.asks)


def error(e: 'BinanceApiException'):
    pass


# Valid limit values are 5, 10, or 20
Пример #22
0
class BinanceInterface(ExchangeInterface):
    def __init__(self, settings, logger, on_tick_callback=None):
        super().__init__(settings, logger, on_tick_callback)
        self.symbol = settings.SYMBOL
        self.client = RequestClient(api_key=settings.API_KEY,
                                    secret_key=settings.API_SECRET)
        self.ws = SubscriptionClient(api_key=settings.API_KEY,
                                     secret_key=settings.API_SECRET)

        self.orders = {}
        self.positions = {}
        self.candles: List[Candlestick] = []
        self.last = 0
        self.open = False
        self.listen_key = ""
        self.init()

    def init(self):
        self.logger.info("loading market data. this may take a moment")
        self.initOrders()
        self.initPositions()
        self.logger.info("got all data. subscribing to live updates.")
        self.listen_key = self.client.start_user_data_stream()

        self.ws.subscribe_user_data_event(self.listen_key, self.callback,
                                          self.error)
        subbarsIntervall = CandlestickInterval.MIN1 if self.settings.MINUTES_PER_BAR <= 60 else CandlestickInterval.HOUR1
        self.ws.subscribe_candlestick_event(self.symbol, subbarsIntervall,
                                            self.callback, self.error)
        self.open = True
        self.lastUserDataKeep = time.time()
        self.logger.info("ready to go")

    def callback(self, data_type: 'SubscribeMessageType', event: 'any'):
        gotTick = False
        # refresh userdata every 15 min
        if self.lastUserDataKeep < time.time() - 15 * 60:
            self.lastUserDataKeep = time.time()
            self.client.keep_user_data_stream()
        # TODO: implement! (update bars, orders and account)
        if data_type == SubscribeMessageType.RESPONSE:
            pass  # what to do herE?
        elif data_type == SubscribeMessageType.PAYLOAD:
            if event.eventType == "kline":
                # {'eventType': 'kline', 'eventTime': 1587064627164, 'symbol': 'BTCUSDT',
                # 'data': <binance_f.model.candlestickevent.Candlestick object at 0x0000016B89856760>}
                if event.symbol == self.symbol:
                    candle: Candlestick = event.data
                    if len(self.candles) > 0:
                        if candle.startTime <= self.candles[
                                0].startTime and candle.startTime > self.candles[
                                    -1].startTime:
                            # somewhere inbetween to replace
                            for idx in range(0, len(self.candles)):
                                if candle.startTime == self.candles[
                                        idx].startTime:
                                    self.candles[idx] = candle
                                    break
                        elif candle.startTime > self.candles[0].startTime:
                            self.candles.insert(0, candle)
                            gotTick = True
                    else:
                        self.candles.append(candle)
                        gotTick = True
            elif (event.eventType == "ACCOUNT_UPDATE"):
                # {'eventType': 'ACCOUNT_UPDATE', 'eventTime': 1587063874367, 'transactionTime': 1587063874365,
                # 'balances': [<binance_f.model.accountupdate.Balance object at 0x000001FAF470E100>,...],
                # 'positions': [<binance_f.model.accountupdate.Position object at 0x000001FAF470E1C0>...]}
                usdBalance = 0
                for b in event.balances:
                    bal: Balance = b
                    if bal.asset == "USDT":
                        usdBalance = bal.walletBalance
                for p in event.positions:
                    pos: Position = p
                    if pos.symbol not in self.positions.keys():
                        self.positions[pos.symbol] = AccountPosition(
                            pos.symbol,
                            avgEntryPrice=float(pos.entryPrice),
                            quantity=float(pos.amount),
                            walletBalance=usdBalance
                            if "USDT" in pos.symbol else 0)
                    else:
                        accountPos = self.positions[pos.symbol]
                        accountPos.quantity = float(pos.amount)
                        accountPos.avgEntryPrice = float(pos.entryPrice)
                        if "USDT" in pos.symbol:
                            accountPos.walletBalance = usdBalance

            elif (event.eventType == "ORDER_TRADE_UPDATE"):
                # {'eventType': 'ORDER_TRADE_UPDATE', 'eventTime': 1587063513592, 'transactionTime': 1587063513589,
                # 'symbol': 'BTCUSDT', 'clientOrderId': 'web_ybDNrTjCi765K3AvOMRK', 'side': 'BUY', 'type': 'LIMIT',
                # 'timeInForce': 'GTC', 'origQty': 0.01, 'price': 6901.0, 'avgPrice': 0.0, 'stopPrice': 0.0,
                # 'executionType': 'NEW', 'orderStatus': 'NEW', 'orderId': 2705199704, 'lastFilledQty': 0.0,
                # 'cumulativeFilledQty': 0.0, 'lastFilledPrice': 0.0, 'commissionAsset': None, 'commissionAmount': None,
                # 'orderTradeTime': 1587063513589, 'tradeID': 0, 'bidsNotional': 138.81, 'asksNotional': 0.0,
                # 'isMarkerSide': False, 'isReduceOnly': False, 'workingType': 'CONTRACT_PRICE'}
                sideMulti = 1 if event.side == 'BUY' else -1
                order: Order = Order(orderId=event.clientOrderId,
                                     stop=event.stopPrice,
                                     limit=event.price,
                                     amount=event.origQty * sideMulti)
                order.exchange_id = event.orderId
                #FIXME: how do i know stop triggered on binance?
                #order.stop_triggered =
                order.executed_amount = event.cumulativeFilledQty * sideMulti
                order.executed_price = event.avgPrice
                order.tstamp = event.transactionTime
                order.execution_tstamp = event.orderTradeTime

                prev: Order = self.orders[
                    order.
                    exchange_id] if order.exchange_id in self.orders.keys(
                    ) else None
                if prev is not None:
                    if prev.tstamp > order.tstamp or abs(
                            prev.executed_amount) > abs(order.executed_amount):
                        # already got newer information, probably the info of the stop order getting
                        # triggered, when i already got the info about execution
                        self.logger.info("ignoring delayed update for %s " %
                                         (prev.id))
                    if order.stop_price is None:
                        order.stop_price = prev.stop_price
                    if order.limit_price is None:
                        order.limit_price = prev.limit_price
                prev = order
                if not prev.active and prev.execution_tstamp == 0:
                    prev.execution_tstamp = datetime.utcnow().timestamp()
                self.orders[order.exchange_id] = prev

                self.logger.info("received order update: %s" % (str(order)))
        else:
            self.logger.warn("Unknown Data in websocket callback")

        if gotTick and self.on_tick_callback is not None:
            self.on_tick_callback()  # got something new

    def error(self, e: 'BinanceApiException'):
        self.exit()
        self.logger.error(e.error_code + e.error_message)

    def initOrders(self):
        apiOrders = self.client.get_open_orders()
        for o in apiOrders:
            order = self.convertOrder(o)
            if order.active:
                self.orders[order.exchange_id] = order

    def convertOrder(self, apiOrder: binance_f.model.Order) -> Order:
        direction = 1 if apiOrder.side == OrderSide.BUY else -1
        order = Order(orderId=apiOrder.clientOrderId,
                      amount=apiOrder.origQty * direction,
                      limit=apiOrder.price,
                      stop=apiOrder.stopPrice)
        order.executed_amount = apiOrder.executedQty * direction
        order.executed_price = apiOrder.avgPrice
        order.active = apiOrder.status in ["NEW", "PARTIALLY_FILLED"]
        order.exchange_id = apiOrder.orderId
        return order

    def initPositions(self):
        balance = self.client.get_balance()
        usdBalance = 0
        for bal in balance:
            if bal.asset == "USDT":
                usdBalance = bal.balance
        api_positions = self.client.get_position()
        self.positions[self.symbol] = AccountPosition(self.symbol, 0, 0, 0)
        if api_positions is not None:
            for pos in api_positions:
                self.positions[pos.symbol] = AccountPosition(
                    pos.symbol,
                    avgEntryPrice=pos.entryPrice,
                    quantity=pos.positionAmt,
                    walletBalance=usdBalance if "USDT" in pos.symbol else 0)

        self.logger.info("starting with %.2f in wallet and pos  %.2f @ %.2f" %
                         (self.positions[self.symbol].walletBalance,
                          self.positions[self.symbol].quantity,
                          self.positions[self.symbol].avgEntryPrice))

    def exit(self):
        self.ws.unsubscribe_all()
        self.open = False

    def internal_cancel_order(self, order: Order):
        if order.exchange_id in self.orders.keys():
            self.orders[order.exchange_id].active = False
        self.client.cancel_order(symbol=self.symbol,
                                 origClientOrderId=order.id)

    def internal_send_order(self, order: Order):
        order_type = OrderType.MARKET
        if order.limit_price is not None:
            if order.stop_price is not None:
                order_type = OrderType.STOP
            else:
                order_type = OrderType.LIMIT
        else:
            order_type = OrderType.STOP_MARKET

        resultOrder: binance_f.model.Order = self.client.post_order(
            symbol=self.symbol,
            side=OrderSide.BUY if order.amount > 0 else OrderSide.SELL,
            ordertype=order_type,
            timeInForce=TimeInForce.GTC,
            quantity=abs(order.amount),
            price=order.limit_price,
            stopPrice=order.stop_price,
            newClientOrderId=order.id)
        order.exchange_id = resultOrder.orderId

    def internal_update_order(self, order: Order):
        self.cancel_order(order)  # stupid binance can't update orders
        self.send_order(order)

    def get_orders(self) -> List[Order]:
        return list(self.orders.values())

    def get_bars(self, timeframe_minutes, start_offset_minutes) -> List[Bar]:
        tf = CandlestickInterval.MIN1 if timeframe_minutes <= 60 else CandlestickInterval.HOUR1

        bars = self.client.get_candlestick_data(symbol=self.symbol,
                                                interval=tf,
                                                limit=1000)

        return self._aggregate_bars(reversed(bars), timeframe_minutes,
                                    start_offset_minutes)

    def recent_bars(self, timeframe_minutes,
                    start_offset_minutes) -> List[Bar]:
        return self._aggregate_bars(self.bars, timeframe_minutes,
                                    start_offset_minutes)

    def _aggregate_bars(self, bars, timeframe_minutes,
                        start_offset_minutes) -> List[Bar]:
        subbars = []
        for b in bars:
            subbars.append(self.convertBar(b))
        return process_low_tf_bars(subbars, timeframe_minutes,
                                   start_offset_minutes)

    def convertBar(self, apiBar: binance_f.model.candlestick.Candlestick):
        return Bar(tstamp=apiBar.openTime / 1000,
                   open=apiBar.open,
                   high=apiBar.high,
                   low=apiBar.low,
                   close=apiBar.close,
                   volume=apiBar.volume)

    def get_instrument(self, symbol=None):
        if symbol is None:
            symbol = self.symbol
        instr: binance_f.model.exchangeinformation.ExchangeInformation = self.client.get_exchange_information(
        )
        for symb in instr.symbols:
            if symb.symbol == symbol:
                baseLength = len(symb.baseAsset)
                lotSize = 0
                tickSize = 0
                for filter in symb.filters:
                    if filter['filterType'] == 'LOT_SIZE':
                        lotSize = filter['stepSize']
                    if filter['filterType'] == 'PRICE_FILTER':
                        tickSize = filter['tickSize']

                return Symbol(
                    symbol=symb.symbol,
                    isInverse=symb.baseAsset != symb.symbol[:baseLength],
                    lotSize=lotSize,
                    tickSize=tickSize,
                    makerFee=0.02,
                    takerFee=0.04)
        return None

    def get_position(self, symbol=None):
        if symbol is None:
            symbol = self.symbol
        return self.positions[symbol] if symbol in self.positions.keys(
        ) else None

    def is_open(self):
        return self.open

    def check_market_open(self):
        return self.open  # TODO: is that the best we can do?

    def update_account(self, account: Account):
        pass
Пример #23
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        for item in event:
            PrintBasic.print_obj(item)
            print("")
        # sub_client.unsubscribe_all()
    else:
        print("Unknown Data:")
    print()

Пример #24
0
import logging
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException

from binance_f.base.printobject import *

logger = logging.getLogger("binance-futures")
logger.setLevel(level=logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(
    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)


def callback(data_type: 'SubscribeMessageType', event: 'any'):
    if data_type == SubscribeMessageType.RESPONSE:
        print("Event ID: ", event)
    elif data_type == SubscribeMessageType.PAYLOAD:
        print("Event type: ", event.eventType)
        print("Event time: ", event.eventTime)
        print("Symbol: ", event.symbol)
        print("Data:")
        PrintBasic.print_obj(event.data)
        sub_client.unsubscribe_all()
    else:
        print("Unknown Data:")
    print()
Пример #25
0
class BinanceInterface(ExchangeInterface):
    def __init__(self, settings, logger, on_tick_callback=None):
        super().__init__(settings, logger, on_tick_callback)
        self.symbol: str = settings.SYMBOL
        self.client = RequestClient(api_key=settings.API_KEY,
                                    secret_key=settings.API_SECRET)
        self.ws = SubscriptionClient(api_key=settings.API_KEY,
                                     secret_key=settings.API_SECRET)

        # for binance the key is the internal id (not the exchange id) cause we can't update order but have to cancel and reopen with same id.
        # that leads to different exchange id, but we need to know its the same.
        self.orders = {}
        self.positions = {}
        self.symbol_object: Symbol = None
        self.candles: List[Candlestick] = []
        self.last = 0
        self.open = False
        self.listen_key = ""
        self.lastUserDataKeep = None
        self.wantedResponses = 0  # needed to wait for realtime
        self.init()

    def init(self):
        self.logger.info("loading market data. this may take a moment")
        self.initOrders()
        self.initPositions()
        self.symbol_object = self.get_instrument()
        self.logger.info("got all data. subscribing to live updates.")
        self.listen_key = self.client.start_user_data_stream()
        self.lastUserDataKeep = time.time()
        self.wantedResponses = 2
        subInt = CandlestickInterval.MIN1 if self.settings.MINUTES_PER_BAR <= 60 else CandlestickInterval.HOUR1
        self.ws.subscribe_candlestick_event(self.symbol.lower(), subInt,
                                            self.callback, self.error)
        self.ws.subscribe_user_data_event(self.listen_key, self.callback,
                                          self.error)
        waitingTime = 0
        while self.wantedResponses > 0 and waitingTime < 100:
            waitingTime += 1
            time.sleep(0.1)

        if self.wantedResponses > 0:
            self.logger.error("got no response to subscription. outa here")
            self.open = False
            return
        self.open = True
        self.logger.info("ready to go")

    def callback(self, data_type: 'SubscribeMessageType', event: 'any'):
        gotTick = False
        fromAccount = False
        # refresh userdata every 5 min
        if self.lastUserDataKeep < time.time() - 5 * 60:
            self.lastUserDataKeep = time.time()
            self.client.keep_user_data_stream()

        if data_type == SubscribeMessageType.RESPONSE:
            self.wantedResponses -= 1  # tell the waiting init that we got it. otherwise we might be too fast
        elif data_type == SubscribeMessageType.PAYLOAD:
            if event.eventType == "kline":
                # {'eventType': 'kline', 'eventTime': 1587064627164, 'symbol': 'BTCUSDT',
                # 'data': <binance_f.model.candlestickevent.Candlestick object at 0x0000016B89856760>}
                if event.symbol == self.symbol:
                    candle: Candlestick = event.data
                    if len(self.candles) > 0:
                        if self.candles[
                                0].startTime >= candle.startTime > self.candles[
                                    -1].startTime:
                            # somewhere inbetween to replace
                            for idx in range(0, len(self.candles)):
                                if candle.startTime == self.candles[
                                        idx].startTime:
                                    self.candles[idx] = candle
                                    break
                        elif candle.startTime > self.candles[0].startTime:
                            self.candles.insert(0, candle)
                            gotTick = True
                    else:
                        self.candles.append(candle)
                        gotTick = True
            elif event.eventType == "ACCOUNT_UPDATE":
                # {'eventType': 'ACCOUNT_UPDATE', 'eventTime': 1587063874367, 'transactionTime': 1587063874365,
                # 'balances': [<binance_f.model.accountupdate.Balance object at 0x000001FAF470E100>,...],
                # 'positions': [<binance_f.model.accountupdate.Position object at 0x000001FAF470E1C0>...]}
                usdBalance = 0
                gotTick = True
                fromAccount = True
                for b in event.balances:
                    bal: Balance = b
                    if bal.asset == "USDT":
                        usdBalance = bal.walletBalance
                for p in event.positions:
                    pos: Position = p
                    if pos.symbol not in self.positions.keys():
                        self.positions[pos.symbol] = AccountPosition(
                            symbol=pos.symbol,
                            avgEntryPrice=float(pos.entryPrice),
                            quantity=float(pos.amount),
                            walletBalance=usdBalance
                            if "USDT" in pos.symbol else 0)
                    else:
                        accountPos = self.positions[pos.symbol]
                        accountPos.quantity = float(pos.amount)
                        accountPos.avgEntryPrice = float(pos.entryPrice)
                        if "USDT" in pos.symbol:
                            accountPos.walletBalance = usdBalance

            elif event.eventType == "ORDER_TRADE_UPDATE":
                # {'eventType': 'ORDER_TRADE_UPDATE', 'eventTime': 1587063513592, 'transactionTime': 1587063513589,
                # 'symbol': 'BTCUSDT', 'clientOrderId': 'web_ybDNrTjCi765K3AvOMRK', 'side': 'BUY', 'type': 'LIMIT',
                # 'timeInForce': 'GTC', 'origQty': 0.01, 'price': 6901.0, 'avgPrice': 0.0, 'stopPrice': 0.0,
                # 'executionType': 'NEW', 'orderStatus': 'NEW', 'orderId': 2705199704, 'lastFilledQty': 0.0,
                # 'cumulativeFilledQty': 0.0, 'lastFilledPrice': 0.0, 'commissionAsset': None, 'commissionAmount': None,
                # 'orderTradeTime': 1587063513589, 'tradeID': 0, 'bidsNotional': 138.81, 'asksNotional': 0.0,
                # 'isMarkerSide': False, 'isReduceOnly': False, 'workingType': 'CONTRACT_PRICE'}
                gotTick = True
                fromAccount = True
                sideMulti = 1 if event.side == 'BUY' else -1
                order: Order = Order(
                    orderId=event.clientOrderId,
                    stop=event.stopPrice if event.stopPrice > 0 else None,
                    limit=event.price if event.price > 0 else None,
                    amount=event.origQty * sideMulti)
                order.exchange_id = event.orderId
                # trigger of a stoplimit in Binance means "update for order -> expired" then "update -> as limit"
                order.stop_triggered = event.type == "LIMIT" and event.stopPrice > 0
                order.executed_amount = event.cumulativeFilledQty * sideMulti
                order.executed_price = event.avgPrice
                order.tstamp = event.transactionTime
                order.execution_tstamp = event.orderTradeTime / 1000
                order.active = event.orderStatus in ["NEW", "PARTIALLY_FILLED"]

                prev: Order = self.orders[
                    order.id] if order.id in self.orders.keys() else None
                if prev is not None:
                    if prev.tstamp > order.tstamp or abs(
                            prev.executed_amount) > abs(order.executed_amount):
                        # already got newer information, probably the info of the stop order getting
                        # triggered, when i already got the info about execution
                        self.logger.info("ignoring delayed update for %s " %
                                         prev.id)
                    if order.stop_price is None:
                        order.stop_price = prev.stop_price
                    if order.limit_price is None:
                        order.limit_price = prev.limit_price
                prev = order
                if not prev.active and prev.execution_tstamp == 0:
                    prev.execution_tstamp = datetime.utcnow().timestamp()
                self.orders[order.id] = prev

                self.logger.info("received order update: %s" % (str(order)))
        else:
            self.logger.warn("Unknown Data in websocket callback")

        if gotTick and self.on_tick_callback is not None:
            self.on_tick_callback(
                fromAccountAction=fromAccount)  # got something new

    def error(self, e: BinanceApiException):
        self.logger.error(e.error_code + ": " + e.error_message)
        self.open = False

    def initOrders(self):
        apiOrders = self.client.get_open_orders()
        for o in apiOrders:
            order = self.convertOrder(o)
            if order.active:
                self.orders[order.id] = order

    @staticmethod
    def convertOrder(apiOrder: binance_f.model.Order) -> Order:
        direction = 1 if apiOrder.side == OrderSide.BUY else -1
        order = Order(
            orderId=apiOrder.clientOrderId,
            amount=apiOrder.origQty * direction,
            limit=apiOrder.price if apiOrder.price > 0 else None,
            stop=apiOrder.stopPrice if apiOrder.stopPrice > 0 else None)
        order.executed_amount = apiOrder.executedQty * direction
        order.executed_price = apiOrder.avgPrice
        order.active = apiOrder.status in ["NEW", "PARTIALLY_FILLED"]
        order.exchange_id = apiOrder.orderId
        return order

    def initPositions(self):
        balance = self.client.get_balance()
        usdBalance = 0
        for bal in balance:
            if bal.asset == "USDT":
                usdBalance = bal.balance
        api_positions = self.client.get_position()
        self.positions[self.symbol] = AccountPosition(
            self.symbol,
            avgEntryPrice=0,
            quantity=0,
            walletBalance=usdBalance if "USDT" in self.symbol else 0)
        if api_positions is not None:
            for pos in api_positions:
                self.positions[pos.symbol] = AccountPosition(
                    pos.symbol,
                    avgEntryPrice=pos.entryPrice,
                    quantity=pos.positionAmt,
                    walletBalance=usdBalance if "USDT" in pos.symbol else 0)

        self.logger.info("starting with %.2f in wallet and pos  %.2f @ %.2f" %
                         (self.positions[self.symbol].walletBalance,
                          self.positions[self.symbol].quantity,
                          self.positions[self.symbol].avgEntryPrice))

    def exit(self):
        self.open = False
        if self.ws is not None:
            self.ws.close()
            self.ws = None
        self.client.close_user_data_stream()

    def internal_cancel_order(self, order: Order):
        if order.id in self.orders.keys():
            self.orders[order.id].active = False
        self.client.cancel_order(symbol=self.symbol,
                                 origClientOrderId=order.id)

    def internal_send_order(self, order: Order):
        if order.limit_price is not None:
            order.limit_price = round(order.limit_price,
                                      self.symbol_object.pricePrecision)
            if order.stop_price is not None:
                order.stop_price = round(order.stop_price,
                                         self.symbol_object.pricePrecision)
                order_type = OrderType.STOP
            else:
                order_type = OrderType.LIMIT
        elif order.stop_price is not None:
            order.stop_price = round(order.stop_price,
                                     self.symbol_object.pricePrecision)
            order_type = OrderType.STOP_MARKET
        else:
            order_type = OrderType.MARKET

        order.amount = round(order.amount,
                             self.symbol_object.quantityPrecision)
        quantityFormat = "{:." + str(
            self.symbol_object.quantityPrecision) + "f}"
        priceFormat = "{:." + str(self.symbol_object.pricePrecision) + "f}"
        # yes have to send the price and quantity in as str (although it wants float) cause otherwise it converts it inernally
        # and that sometimes f**k up the precision (0.023 -> 0.02299999999)
        resultOrder: binance_f.model.Order = self.client.post_order(
            symbol=self.symbol,
            side=OrderSide.BUY if order.amount > 0 else OrderSide.SELL,
            ordertype=order_type,
            timeInForce=TimeInForce.GTC
            if order_type in [OrderType.LIMIT, OrderType.STOP] else None,
            quantity=quantityFormat.format(abs(order.amount)),
            price=priceFormat.format(order.limit_price)
            if order.limit_price is not None else None,
            stopPrice=priceFormat.format(order.stop_price)
            if order.stop_price is not None else None,
            newClientOrderId=order.id)
        order.exchange_id = resultOrder.orderId

    def internal_update_order(self, order: Order):
        self.cancel_order(order)  # stupid binance can't update orders
        self.on_tick_callback(True)  # triggers a reset of the tick-delay.
        # otherwise we risk a tick to be calced after the cancel, before the new order
        self.send_order(order)
        self.on_tick_callback(True)  # triggers a reset of the tick-delay

    def get_orders(self) -> List[Order]:
        return list(self.orders.values())

    def get_bars(self, timeframe_minutes, start_offset_minutes) -> List[Bar]:
        tf = CandlestickInterval.MIN1 if timeframe_minutes <= 60 else CandlestickInterval.HOUR1

        bars = self.client.get_candlestick_data(symbol=self.symbol,
                                                interval=tf,
                                                limit=1000)

        subbars = []
        for b in reversed(bars):
            subbars.append(self.convertBar(b))
        return process_low_tf_bars(subbars, timeframe_minutes,
                                   start_offset_minutes)

    def recent_bars(self, timeframe_minutes,
                    start_offset_minutes) -> List[Bar]:
        subbars = []
        for b in self.candles:
            subbars.append(self.convertBarevent(b))
        return process_low_tf_bars(subbars, timeframe_minutes,
                                   start_offset_minutes)

    @staticmethod
    def convertBar(apiBar: binance_f.model.candlestick.Candlestick):
        return Bar(tstamp=apiBar.openTime / 1000,
                   open=float(apiBar.open),
                   high=float(apiBar.high),
                   low=float(apiBar.low),
                   close=float(apiBar.close),
                   volume=float(apiBar.volume))

    @staticmethod
    def convertBarevent(apiBar: binance_f.model.candlestickevent.Candlestick):
        return Bar(tstamp=apiBar.startTime / 1000,
                   open=float(apiBar.open),
                   high=float(apiBar.high),
                   low=float(apiBar.low),
                   close=float(apiBar.close),
                   volume=float(apiBar.volume))

    @staticmethod
    def barArrayToBar(b):
        return Bar(tstamp=b[0] / 1000,
                   open=float(b[1]),
                   high=float(b[2]),
                   low=float(b[3]),
                   close=float(b[4]),
                   volume=float(b[5]))

    def get_instrument(self, symbol=None):
        if symbol is None:
            symbol = self.symbol
        instr: binance_f.model.exchangeinformation.ExchangeInformation = self.client.get_exchange_information(
        )
        for symb in instr.symbols:
            if symb.symbol == symbol:
                baseLength = len(symb.baseAsset)
                lotSize = 0
                tickSize = 0
                for filterIt in symb.filters:
                    if filterIt['filterType'] == 'LOT_SIZE':
                        lotSize = filterIt['stepSize']
                    if filterIt['filterType'] == 'PRICE_FILTER':
                        tickSize = filterIt['tickSize']

                return Symbol(
                    symbol=symb.symbol,
                    isInverse=symb.baseAsset != symb.symbol[:baseLength],
                    lotSize=lotSize,
                    tickSize=tickSize,
                    makerFee=0.02,
                    takerFee=0.04,
                    pricePrecision=symb.pricePrecision,
                    quantityPrecision=symb.quantityPrecision)
        return None

    def get_position(self, symbol=None):
        if symbol is None:
            symbol = self.symbol
        return self.positions[symbol] if symbol in self.positions.keys(
        ) else None

    def is_open(self):
        return self.open

    def check_market_open(self):
        return self.open  # TODO: is that the best we can do?

    def update_account(self, account: Account):
        pos = self.positions[self.symbol]
        account.open_position = pos
        account.equity = pos.walletBalance
        account.usd_equity = account.equity