コード例 #1
0
ファイル: exchange.py プロジェクト: daryl7/daryl
    def order(self, body):
        with BitFlyer.__urlopen("POST", "/v1/me/sendchildorder",
                                data=body) as res:
            html = res.read().decode("utf-8")
            applog.info(html)
            child_order_acceptance_id = json.loads(
                html)["child_order_acceptance_id"]

        retry_count = 0
        while True:
            if retry_count > 3:
                assert ("failed order")

            time.sleep(3)
            retry_count += 1
            with BitFlyer.__urlopen("GET",
                                    "/v1/me/getchildorders",
                                    param={
                                        "child_order_acceptance_id":
                                        child_order_acceptance_id
                                    }) as res:
                html = res.read().decode("utf-8")
                if len(json.loads(html)) > 0:
                    applog.info(html)
                    commission = json.loads(html)[0]["total_commission"]
                    break
        return [child_order_acceptance_id, commission]
コード例 #2
0
ファイル: exchange.py プロジェクト: daryl7/daryl
    def __urlopen(method, path, *, param=None, data={}):
        paramtext = ""
        body = ""
        if method == "POST":
            body = json.dumps(data)
        else:
            if (param):
                paramtext = "?" + urllib.parse.urlencode(param)

        timestamp = str(time.time())
        text = timestamp + method + path + paramtext + body
        applog.info(text)
        sign = hmac.new(bytes(bitflyer_api_secret.encode('ascii')),
                        bytes(text.encode('ascii')),
                        hashlib.sha256).hexdigest()

        headers = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
            'ACCESS-KEY': bitflyer_api_key,
            'ACCESS-TIMESTAMP': timestamp,
            'ACCESS-SIGN': sign,
            'Content-Type': 'application/json'
        }
        if method == "POST":
            req = urllib.request.Request(url=BitFlyer.__api_endpoint + path +
                                         paramtext,
                                         data=json.dumps(data).encode("utf-8"),
                                         headers=headers)
        else:
            req = urllib.request.Request(url=BitFlyer.__api_endpoint + path +
                                         paramtext,
                                         headers=headers)
        return fetch_url(req)
コード例 #3
0
ファイル: exchange.py プロジェクト: daryl7/daryl
    def health_check(self, dryrun):
        if dryrun:
            return True

        with BitFlyer.__urlopen_public("GET", "/v1/getboardstate") as res:
            html = res.read().decode("utf-8")
        j = json.loads(html)
        if j["state"] == "RUNNING" and j["health"] in [
                "NORMAL", "BUSY", "VERY BUSY"
        ]:
            applog.info("Bitflyer API status:" + j["state"] + ", health:" +
                        j["health"])
            return True
        else:
            applog.warning("Bitflyer API has problem.")
            applog.warning("state:" + j["state"] + ", health:" + j["health"])
            applog.warning(
                "watch:https://lightning.bitflyer.jp/docs?lang=ja&_ga=2.27791676.1496421283.1524886778-454668974.1522570784#%E6%9D%BF%E3%81%AE%E7%8A%B6%E6%85%8B"
            )
            return False
コード例 #4
0
    def run(self, run_mode, is_binance, is_poloniex):
        applog.init(self.__prepare_dir(self.log_dir + "/app.log"))

        if run_mode == "RealTrade":
            dryrun = False
        else:
            dryrun = True

        mailer = Mailer()
        if mailer.is_use():
            if not mailer.checkmailer():
                applog.error("mailer not activation!")
                sys.exit()

        applog.info("========================================")
        applog.info("Start Triangular Arbitrage. RunMode = " + run_mode)
        applog.info("binance.comission_fee: %0.8f" %
                    self.binance.comission_fee)
        applog.info("profit_lower_limit: %0.8f" % self.profit_lower_limit)
        applog.info("expected_final_profit_lower_btc_limit: %0.8f" %
                    self.expected_final_profit_lower_btc_limit)
        applog.info("risk_hedge_of_target_currency_price: %d" %
                    self.risk_hedge_of_target_currency_price)
        applog.info("========================================")

        self.binance.refresh_exchange_info()

        try:
            self.main_loop(dryrun, is_binance, is_poloniex)
        except Exception as e:
            applog.error(traceback.format_exc())
            mailer.sendmail(traceback.format_exc(),
                            "Assertion - Daryl Triangular")
コード例 #5
0
    def make_final_order(self, _orders, base_currency_name, route_type,
                         risk_hedge):
        if self.__get_asset_lot(base_currency_name) == 0:
            print("You are no money. " + base_currency_name)
            return None

        via_symbol = _orders[1]["symbol"]
        via_currency_name = self.__get_basename_from_symbol(via_symbol)

        final_orders = []
        for order in _orders:
            symbol = order["symbol"]
            depth = self.binance.depth(symbol)
            lot = 0.0
            for ask in depth["asks" if order["side"] == "BUY" else "bids"]:
                price = float(ask[0])
                lot = lot + float(ask[1])
                if lot * price / risk_hedge > self.__get_lower_limit(
                        self.__get_basename_from_symbol(symbol), True):
                    break
            final_orders.append({
                "symbol": order["symbol"],
                "side": order["side"],
                "price": price,
                "lot": lot,
            })

        if route_type == "BUY_BUY_SELL":
            final_orders[0][
                "base_lot"] = final_orders[0]["price"] * final_orders[0]["lot"]
            final_orders[1]["base_lot"] = final_orders[1][
                "price"] * final_orders[1]["lot"] * final_orders[0]["price"]
            final_orders[2][
                "base_lot"] = final_orders[2]["price"] * final_orders[2]["lot"]
        elif route_type == "BUY_SELL_SELL":
            final_orders[0][
                "base_lot"] = final_orders[0]["price"] * final_orders[0]["lot"]
            final_orders[1]["base_lot"] = final_orders[1][
                "price"] * final_orders[1]["lot"] * final_orders[2]["price"]
            final_orders[2][
                "base_lot"] = final_orders[2]["price"] * final_orders[2]["lot"]
        elif route_type == "BUY_SELL_BUY":
            final_orders[0][
                "base_lot"] = final_orders[0]["price"] * final_orders[0]["lot"]
            final_orders[1]["base_lot"] = final_orders[1][
                "price"] * final_orders[1]["lot"] / final_orders[2]["price"]
            final_orders[2]["base_lot"] = final_orders[2]["lot"]
        elif route_type == "SELL_BUY_SELL":
            final_orders[0]["base_lot"] = final_orders[0]["lot"]
            final_orders[1]["base_lot"] = final_orders[1][
                "price"] * final_orders[1]["lot"] / final_orders[0]["price"]
            final_orders[2][
                "base_lot"] = final_orders[2]["price"] * final_orders[2]["lot"]

        raw_min_base_lot = min([
            final_orders[0]["base_lot"], final_orders[1]["base_lot"],
            final_orders[2]["base_lot"]
        ])
        min_base_lot = raw_min_base_lot / risk_hedge
        min_base_lot = min(min_base_lot,
                           self.__get_asset_lot(base_currency_name))

        if min_base_lot < self.__get_lower_limit(base_currency_name, True):
            applog.info(
                "Total must be at latest %f%s. (min_base_lot = %0.8f)" %
                (self.__get_lower_limit(base_currency_name, True),
                 base_currency_name, min_base_lot))
            return None

        if route_type == "BUY_BUY_SELL":
            final_orders[0]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["lot"] * min_base_lot /
                final_orders[0]["base_lot"],
                final_orders[0]["symbol"])  # via lot
            final_orders[1]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["final_lot"] / final_orders[1]["price"],
                final_orders[1]["symbol"],
                final_orders[2]["symbol"])  # target lot
            final_orders[2]["final_lot"] = final_orders[1][
                "final_lot"]  # target lot
        elif route_type == "BUY_SELL_SELL":
            final_orders[0]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["lot"] * min_base_lot /
                final_orders[0]["base_lot"], final_orders[0]["symbol"],
                final_orders[1]["symbol"])  # target lot
            final_orders[1]["final_lot"] = final_orders[0][
                "final_lot"]  # target lot
            final_orders[2]["final_lot"] = self.binance.lot_filter(
                final_orders[1]["final_lot"] * final_orders[1]["price"],
                final_orders[2]["symbol"])  # via lot
        elif route_type == "BUY_SELL_BUY":
            final_orders[0]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["lot"] * min_base_lot /
                final_orders[0]["base_lot"], final_orders[0]["symbol"],
                final_orders[1]["symbol"])  # target lot
            final_orders[1]["final_lot"] = final_orders[0][
                "final_lot"]  # target lot
            final_orders[2]["final_lot"] = self.binance.lot_filter(
                final_orders[1]["final_lot"] * final_orders[0]["price"],
                final_orders[0]["symbol"])  # base lot
        elif route_type == "SELL_BUY_SELL":
            final_orders[0]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["lot"] * min_base_lot /
                final_orders[0]["base_lot"],
                final_orders[0]["symbol"])  # base lot
            final_orders[1]["final_lot"] = self.binance.lot_filter(
                final_orders[0]["final_lot"] / final_orders[2]["price"],
                final_orders[1]["symbol"],
                final_orders[2]["symbol"])  # target lot
            final_orders[2]["final_lot"] = final_orders[1][
                "final_lot"]  # target lot

        via_lot = final_orders[1]["final_lot"] * final_orders[1]["price"]
        if via_lot < self.__get_lower_limit(via_currency_name, False):
            applog.info("Total must be at latest %f%s. (via_lot = %0.8f)" %
                        (self.__get_lower_limit(via_currency_name, False),
                         via_currency_name, via_lot))
            return None

        return final_orders
コード例 #6
0
    def trade_binance(self, triangle_order, dryrun):
        start_t = datetime.now()
        mailer = Mailer()

        route = triangle_order[2]
        base_currency_name = route[:3]
        viasymbole = triangle_order[8].split(":")[0]
        via_currency_name = viasymbole[len(viasymbole) - 3:]
        route_type = triangle_order[16]
        pre_orders = [
            {
                "symbol": triangle_order[4].split(":")[0],
                "side": triangle_order[4].split(":")[1],
                "price": float(triangle_order[5]),
                "lot": float(triangle_order[6]),
                "base_lot": float(triangle_order[7]),
            },
            {
                "symbol": triangle_order[8].split(":")[0],
                "side": triangle_order[8].split(":")[1],
                "price": float(triangle_order[9]),
                "lot": float(triangle_order[10]),
                "base_lot": float(triangle_order[11]),
            },
            {
                "symbol": triangle_order[12].split(":")[0],
                "side": triangle_order[12].split(":")[1],
                "price": float(triangle_order[13]),
                "lot": float(triangle_order[14]),
                "base_lot": float(triangle_order[15]),
            },
        ]

        orders = self.make_final_order(pre_orders, base_currency_name,
                                       route_type, 2)
        if orders is None:
            return False

        applog.info("")
        order_count = 0
        for order in orders:
            pre_order = pre_orders[order_count]
            applog.info("%s(%s)" % (order["symbol"], order["side"]))
            applog.info(
                "price:     %5.8f => %5.8f %s" %
                (pre_order["price"], order["price"],
                 "" if pre_order["price"] == order["price"] else "(%+0.8f)" %
                 (order["price"] - pre_order["price"])))
            applog.info(
                "lot:       %5.8f => %5.8f %s" %
                (pre_order["lot"], order["lot"],
                 "" if pre_order["lot"] == order["lot"] else "(%+0.8f)" %
                 (order["lot"] - pre_order["lot"])))
            applog.info(
                "base_lot:  %5.8f => %5.8f %s" %
                (pre_order["base_lot"], order["base_lot"], "" if
                 pre_order["base_lot"] == order["base_lot"] else "(%+0.8f)" %
                 (order["base_lot"] - pre_order["base_lot"])))
            applog.info("final_lot:            => %5.8f" % order["final_lot"])
            order_count += 1
            applog.info("")

        if route_type == "BUY_SELL_BUY":
            expected_profit = orders[2][
                "final_lot"] - orders[0]["final_lot"] * orders[0]["price"]
            expected_fee = (lambda x: x - x *
                            (1 - self.binance.comission_fee)**3)(
                                orders[2]["final_lot"])
        elif route_type == "SELL_BUY_SELL":
            expected_profit = orders[2]["final_lot"] * orders[2][
                "price"] - orders[0]["final_lot"]
            expected_fee = (lambda x: x - x *
                            (1 - self.binance.comission_fee)**3)(
                                orders[2]["final_lot"] * orders[2]["price"])
        else:
            expected_profit = orders[2]["final_lot"] * orders[2][
                "price"] - orders[0]["final_lot"] * orders[0]["price"]
            expected_fee = (lambda x: x - x *
                            (1 - self.binance.comission_fee)**3)(
                                orders[2]["final_lot"] * orders[2]["price"])
        expected_final_profit = expected_profit - expected_fee

        if expected_final_profit < self.expected_final_profit_lower_btc_limit:
            applog.info(
                "Situation has changed. expected_final_revenue = %0.8f < %0.8f"
                % (expected_final_profit,
                   self.expected_final_profit_lower_btc_limit))
            return False

        msgs = [""]
        msgs.append("[beta] %d JPY" % ((expected_final_profit) * 1000000))
        msgs.append("Expected Final Profit:%0.8f%s" %
                    (expected_final_profit, base_currency_name))
        msgs.append("Expected fee:%0.8f%s" %
                    (expected_fee, base_currency_name))
        msgs.append(
            "Expected Profit:%0.8f%s    1st lot(%0.8f(%0.8f%s)) => 3rd lot(%0.8f(%0.8f%s))"
            % (
                expected_profit,
                base_currency_name,
                orders[0]["final_lot"],
                orders[0]["final_lot"] * orders[0]["price"],
                base_currency_name,
                orders[2]["final_lot"],
                orders[2]["final_lot"] * orders[2]["price"],
                base_currency_name,
            ))
        msgs.append("")
        msgs.append(
            "1st order:%s(%s), price:%0.8f, lot:%0.8f, base_lot:%0.8f, final_lot:%0.8f"
            %
            (orders[0]["symbol"], orders[0]["side"], orders[0]["price"],
             orders[0]["lot"], orders[0]["base_lot"], orders[0]["final_lot"]))
        msgs.append(
            "2nd order:%s(%s), price:%0.8f, lot:%0.8f, base_lot:%0.8f, final_lot:%0.8f"
            %
            (orders[1]["symbol"], orders[1]["side"], orders[1]["price"],
             orders[1]["lot"], orders[1]["base_lot"], orders[1]["final_lot"]))
        msgs.append(
            "3rd order:%s(%s), price:%0.8f, lot:%0.8f, base_lot:%0.8f, final_lot:%0.8f"
            %
            (orders[2]["symbol"], orders[2]["side"], orders[2]["price"],
             orders[2]["lot"], orders[2]["base_lot"], orders[2]["final_lot"]))

        for msg in msgs:
            applog.info(msg)

        mailer.sendmail("\n".join(msgs),
                        "%s - Create order - Daryl Triangular" % route)

        if not dryrun:
            order_count = 0
            final_status = ""
            for order in orders:
                r = self.binance.order(
                    order["symbol"],
                    order["side"],
                    binance.client.Client.ORDER_TYPE_LIMIT,
                    binance.client.Client.TIME_IN_FORCE_GTC,
                    order["final_lot"],
                    "%0.8f" % order["price"],
                )
                applog.info("binance.create_order" + str(r))
                i = 0
                while True:
                    try:
                        r = self.binance.get_order(r["symbol"], r["orderId"])
                    except BinanceAPIException as e:
                        if e.status_code == -2013:  # NO_SUCH_ORDER
                            applog.info(
                                "BinanceAPIException: Order does not exist. (%d)"
                                % i)
                            if i < 30:
                                time.sleep(0.001)
                            else:
                                time.sleep(10)
                            i += 1
                            continue

                    if r["status"] == binance.client.Client.ORDER_STATUS_FILLED:
                        applog.info("filled.")
                        order_count += 1
                        break
                    elif r["status"] in [
                            binance.client.Client.ORDER_STATUS_NEW,
                            binance.client.Client.
                            ORDER_STATUS_PARTIALLY_FILLED,
                    ]:
                        applog.info(
                            "%s,%s,order_count:%d,price:%s,lot:%s,status:%s(%d)"
                            % (r["symbol"], r["side"], order_count, r["price"],
                               r["origQty"], r["status"], i))
                        if i < 30:
                            time.sleep(0.001)
                        elif i < 100:
                            if order_count == 0 and r[
                                    "status"] == binance.client.Client.ORDER_STATUS_NEW:
                                applog.warning(
                                    "Skip triangular arbitrage. status=" +
                                    r["status"])
                                cancel_result = self.binance.cancel_order(
                                    r["symbol"], r["orderId"])
                                applog.info("Canceled. result=" +
                                            str(cancel_result))
                                mailer.sendmail(
                                    "%s,%s" % (r["symbol"], r["orderId"]),
                                    "Canceled - Daryl Triangular")
                                final_status = "cancel"
                                break
                            time.sleep(0.01)
                        else:
                            time.sleep(10)
                        i += 1
                    else:
                        # binance.client.Client.ORDER_STATUS_CANCELED
                        # binance.client.Client.ORDER_STATUS_EXPIRED
                        # binance.client.Client.ORDER_STATUS_PENDING_CANCEL
                        # binance.client.Client.ORDER_STATUS_REJECTED
                        if order_count == 0:
                            applog.warning(
                                "Skip triangular arbitrage. status=" +
                                r["status"])
                            cancel_result = self.binance.cancel_order(
                                r["symbol"], r["orderId"])
                            applog.info("Canceled. result=" +
                                        str(cancel_result))
                            mailer.sendmail(
                                "%s,%s" % (r["symbol"], r["orderId"]),
                                "Canceled - Daryl Triangular")
                            final_status = "cancel"
                            break
                        else:
                            applog.error(
                                "Failed triangular arbitrage. status=" +
                                r["status"])
                            mailer.sendmail(
                                "%s,%s" % (r["symbol"], r["orderId"]),
                                "Failed - Daryl Triangular")
                            final_status = "failed"
                            break
                if final_status in ["cancel", "failed"]:
                    break
            if order_count == 3:
                mailer.sendmail(route, "Successful - Daryl Triangular")
                final_status = "successful"
            self.trade_log(start_t, "Binance", route, expected_final_profit,
                           final_status)
        return True