예제 #1
0
    def send_order(self, direction, action, type, symbol, price, amount, client_order_id=None):
        target_coin, base_coin = xq.get_symbol_coins(symbol)
        binance_side = self.__trans_side(direction, action)
        decimal = ts.get_decimal(amount)

        if binance_side is SIDE_BUY:
            balance = self.get_balances(base_coin)
            if balance:
                balance = Decimal(balance['free'])
            else:
                balance = Decimal(0)
            if balance < Decimal(amount) * Decimal(price):
                loan_amount = ts.reserve_float_ceil(float(Decimal(amount) * Decimal(price) - balance), 0)
                log.info('loan: coin(%s), amount(%f)' % (base_coin, loan_amount))
                self.loan(base_coin, loan_amount)

        elif binance_side is SIDE_SELL:
            balance = self.get_balances(target_coin)
            if balance:
                balance = Decimal(balance['free'])
            else:
                balance = Decimal(str(0))
            if balance < Decimal(str(amount)):
                loan_amount = ts.reserve_float_ceil(float(Decimal(amount) - balance), decimal)
                log.info('loan: coin(%s), amount(%f)' % (target_coin.upper(), loan_amount))
                self.loan(target_coin.upper(), loan_amount)
        else:
            return

        return self.create_order(direction, action, type, symbol,
                          price, amount, client_order_id)
예제 #2
0
    def sync_orders(self, symbol):
        orders = self.get_open_orders(symbol)
        if not orders:
            return

        df_amount, df_value = self.__exchange.get_deals(symbol)
        for order in orders:
            self.log_debug("order: %r" % order)
            order_id = order["order_id"]
            order_amount = order["amount"]

            if order_id not in df_amount.index:
                """ 没有成交信息 """
                continue

            deal_amount = df_amount[order_id]

            target_coin, base_coin = xq.get_symbol_coins(symbol)
            deal_amount = ts.reserve_float(deal_amount,
                                           self.config["digits"][target_coin])
            deal_value = df_value[order_id]

            status = xq.ORDER_STATUS_OPEN
            if deal_amount > order_amount:
                self.log_error("最新成交数量(%f)大于委托数量(%f)  %g" %
                               (deal_amount, order_amount,
                                (deal_amount - order_amount)))
                continue
            elif deal_amount == order_amount:
                status = xq.ORDER_STATUS_CLOSE
            else:
                if deal_amount < order["deal_amount"]:
                    self.log_warning("最新成交数量小于委托里记载的旧成交数量")
                    continue
                elif deal_amount == order["deal_amount"]:
                    self.log_info("成交数量没有更新")
                else:
                    pass
                if self.__exchange.order_status_is_close(symbol, order_id):
                    status = xq.ORDER_STATUS_CLOSE
            self.log_debug(
                "deal_amount: %f,  deal_value: %g,  deal_price: %g" %
                (deal_amount, deal_value, deal_value / deal_amount))
            self.td_db.update_one(
                DB_ORDERS_NAME,
                order["_id"],
                {
                    "deal_amount": deal_amount,
                    "deal_value": deal_value,
                    "status": status,
                },
            )
        return
예제 #3
0
    def _get_position_from_orders(self, symbol, orders):
        cycle_first_order = None

        history_profit = 0
        history_commission = 0
        cycle_amount = 0
        cycle_value = 0
        cycle_commission = 0
        target_coin, base_coin = xq.get_symbol_coins(symbol)
        for order in orders:
            if not self.check_order(order):
                return None

            if order["action"] == xq.OPEN_POSITION:
                if cycle_amount == 0:
                    cycle_first_order = order
                cycle_amount += order["deal_amount"]
            else:
                cycle_amount -= order["deal_amount"]
            cycle_amount = ts.reserve_float(cycle_amount,
                                            self.config["digits"][target_coin])
            cycle_value += self.get_order_value(order)
            cycle_commission += self.get_order_commission(order)

            if cycle_amount == 0:
                history_profit += cycle_value - cycle_commission
                history_commission += cycle_commission
                cycle_value = 0
                cycle_commission = 0

        # 持仓信息
        pst_info = {
            "amount": cycle_amount,  # 数量
            "value": cycle_value,  # 金额
            "commission": cycle_commission,  # 佣金
            "history_profit": history_profit,  # 历史利润
            "history_commission": history_commission,  # 历史佣金
        }

        if cycle_amount > 0:
            pst_info["price"] = abs(cycle_value) / cycle_amount
            pst_info["cost_price"] = (abs(cycle_value) +
                                      cycle_commission) / cycle_amount

            pst_info["direction"] = cycle_first_order["direction"]
            pst_info["start_time"] = datetime.fromtimestamp(
                cycle_first_order["create_time"])
            if "high" in order:
                pst_info["high"] = cycle_first_order["high"]
                pst_info["low"] = cycle_first_order["low"]

        return pst_info
예제 #4
0
    def calc_order(self, symbol, orders):
        amount = 0
        buy_value = 0
        sell_value = 0
        buy_commission = 0
        sell_commission = 0

        total_profit = 0

        target_coin, base_coin = xq.get_symbol_coins(symbol)
        for index, order in enumerate(orders):
            if index == 0:
                order["cycle_id"] = 0
            else:
                pre_order = orders[index - 1]
                order["cycle_id"] = pre_order["cycle_id"]
                if order["cycle_id"] != pre_order["side"] and order[
                        "side"] == xq.SIDE_BUY:
                    order["cycle_id"] += 1

            commission = order["deal_value"] * self.config["commission_rate"]
            deal_price = order["deal_value"] / order["deal_amount"]

            if order["side"] == xq.SIDE_BUY:
                amount += order["deal_amount"]
                buy_value += order["deal_value"]
                buy_commission += commission
            else:
                amount -= order["deal_amount"]
                sell_value += order["deal_value"]
                sell_commission += commission

            amount = ts.reserve_float(amount,
                                      self.config["digits"][target_coin])

            buy_cost = buy_value + buy_commission
            order[
                "profit"] = deal_price * amount + sell_value - sell_commission - buy_cost
            order["profit_rate"] = order["profit"] / buy_cost
            order["total_profit"] = (total_profit + order["profit"])
            order["total_profit_rate"] = order["total_profit"] / self.value

            if amount == 0:
                total_profit += order["profit"]

                buy_value = 0
                sell_value = 0
                buy_commission = 0
                sell_commission = 0

        return orders
예제 #5
0
    def stat_orders(self, symbol, orders):
        cycle_id = 1

        history_profit = 0
        history_commission = 0
        cycle_amount = 0
        cycle_value = 0
        cycle_commission = 0
        target_coin, base_coin = xq.get_symbol_coins(symbol)
        for order in orders:
            if not self.check_order(order):
                return None

            order["cycle_id"] = cycle_id

            if order["action"] == xq.OPEN_POSITION:
                cycle_amount += order["deal_amount"]
            else:
                cycle_amount -= order["deal_amount"]
            cycle_amount = ts.reserve_float(cycle_amount,
                                            self.config["digits"][target_coin])
            cycle_value += self.get_order_value(order)
            cycle_commission += self.get_order_commission(order)

            deal_price = order["deal_value"] / order["deal_amount"]
            cycle_profit = self.get_floating_profit(order["direction"],
                                                    cycle_amount, cycle_value,
                                                    cycle_commission,
                                                    deal_price)
            order["floating_profit"] = cycle_profit
            order["history_profit"] = history_profit
            order["total_profit"] = cycle_profit + history_profit

            open_value = self.value
            if self.config["mode"] == 1:
                open_value += history_profit
            order[
                "floating_profit_rate"] = order["floating_profit"] / open_value
            order["history_profit_rate"] = order["history_profit"] / self.value
            order["total_profit_rate"] = order["total_profit"] / self.value

            if cycle_amount == 0:
                history_profit += cycle_profit
                history_commission += cycle_commission
                cycle_value = 0
                cycle_commission = 0
                cycle_id += 1

        return orders
예제 #6
0
파일: engine.py 프로젝트: xiebing77/xquant
    def _get_position(self, symbol, orders, cur_price):
        target_coin, base_coin = xq.get_symbol_coins(symbol)

        #info = self._get_position_from_orders(symbol, orders)
        info = get_pst_by_orders(orders, self.config["commission_rate"])

        if orders:
            info["pst_rate"] = orders[-1]["pst_rate"]
            pst_first_order = get_pst_first_order(orders)
            info[POSITON_HIGH_KEY] = pst_first_order[POSITON_HIGH_KEY]
            info[POSITON_HIGH_TIME_KEY] = pst_first_order[
                POSITON_HIGH_TIME_KEY]
            info[POSITON_LOW_KEY] = pst_first_order[POSITON_LOW_KEY]
            info[POSITON_LOW_TIME_KEY] = pst_first_order[POSITON_LOW_TIME_KEY]

        if self.log_switch:
            com_info = "  %s current price( %g )" % (symbol, cur_price)
            his_info = "  limit: %g;  history_profit: %g,  history_commission: %g,  history_profit_rate: %g%%" % (
                self.value, info["history_profit"], info["history_commission"],
                (info["history_profit"] * 100 / self.value))
            self.log_info(com_info + ";  " + his_info)

            if info[POSITON_AMOUNT_KEY]:
                tmp_fmt = " %s: value(%g), amount(%g), commission(%g)"
                self.log_info(
                    tmp_fmt %
                    ("init", info[POSITON_VALUE_KEY], info[POSITON_AMOUNT_KEY],
                     info[POSITON_COMMISSION_KEY]))
                if LOCK_POSITON_AMOUNT_KEY in info:
                    self.log_info(tmp_fmt %
                                  ("lock", info[LOCK_POSITON_VALUE_KEY],
                                   info[LOCK_POSITON_AMOUNT_KEY],
                                   info[LOCK_POSITON_COMMISSION_KEY]))

                price_info = "  pirce:  open(%f),  cost(%f),  lock(%f)" % (
                    get_open_price(info), get_cost_price(info),
                    get_lock_price(info))
                self.log_info(price_info)

                floating_profit, total_profit, floating_profit_rate, total_profit_rate = get_floating_profit(
                    info, self.value, self.config["mode"], cur_price)
                profit_info = "  profit: %g,  profit_rate: %.2f%%, total_profit: %s,  total_profit_rate: %.2f%%)" % (
                    floating_profit, floating_profit_rate * 100, total_profit,
                    total_profit_rate * 100)
                self.log_info(profit_info)

        # print(info)
        return info
예제 #7
0
    def _get_position(self, symbol, orders, cur_price):
        target_coin, base_coin = xq.get_symbol_coins(symbol)

        info = self._get_position_from_orders(symbol, orders)

        total_profit = info["history_profit"]
        if info["amount"] > 0:
            cycle_profit = self.get_floating_profit(info["direction"],
                                                    info["amount"],
                                                    info["value"],
                                                    info["commission"],
                                                    cur_price)
            total_profit += cycle_profit

            open_value = self.value
            if self.config["mode"] == 1:
                open_value += info["history_profit"]

            info["floating_profit"] = cycle_profit
            info["floating_profit_rate"] = cycle_profit / open_value

        if orders:
            info["pst_rate"] = orders[-1]["pst_rate"]

        self.log_info(
            "symbol( %s ); current price( %g ); position(%s%s%s  history_profit: %g,  history_commission: %g,  history_profit_rate: %g,  total_profit_rate: %g)"
            %
            (symbol, cur_price,
             "amount: %f,  price: %g, cost price: %g,  value: %g,  commission: %g,  limit: %g,  profit: %g,"
             % (
                 info["amount"],
                 info["price"],
                 info["cost_price"],
                 info["value"],
                 info["commission"],
                 self.value,
                 info["floating_profit"],
             ) if info["amount"] else "", "  profit rate: %g," %
             (info["floating_profit_rate"]) if info["value"] else "",
             "  start_time: %s\n," %
             info["start_time"].strftime("%Y-%m-%d %H:%M:%S")
             if "start_time" in info and info["start_time"] else "",
             info["history_profit"], info["history_commission"],
             (info["history_profit"] / self.value),
             (total_profit / self.value)))
        # print(info)
        return info
예제 #8
0
파일: engine.py 프로젝트: leezizi/xquant
    def _get_position(self, symbol, orders, cur_price):
        target_coin, base_coin = xq.get_symbol_coins(symbol)

        #info = self._get_position_from_orders(symbol, orders)
        info = get_pst_by_orders(orders, self.config["commission_rate"])

        if orders:
            info["pst_rate"] = orders[-1]["pst_rate"]
            for pst_first_order in reversed(orders):
                if pst_first_order[ORDER_ACTION_KEY] == bl.OPEN_POSITION:
                    break
            info[POSITON_HIGH_KEY] = pst_first_order[POSITON_HIGH_KEY]
            info[POSITON_HIGH_TIME_KEY] = pst_first_order[
                POSITON_HIGH_TIME_KEY]
            info[POSITON_LOW_KEY] = pst_first_order[POSITON_LOW_KEY]
            info[POSITON_LOW_TIME_KEY] = pst_first_order[POSITON_LOW_TIME_KEY]

        if self.log_switch:
            open_value = self.value
            if self.config["mode"] == 1:
                open_value += info["history_profit"]
            floating_profit = get_floating_profit(info, cur_price)
            floating_profit_rate = floating_profit / open_value
            total_profit = floating_profit + info["history_profit"]

            sub_info1 = "amount: %f,  price: %g, cost price: %g,  value: %g,  commission: %g,  limit: %g,  profit: %g," % (
                info["amount"], info["price"], get_cost_price(info),
                info["value"], info["commission"], self.value,
                floating_profit) if info["amount"] else ""
            sub_info2 = "  profit rate: %g%%," % (floating_profit_rate *
                                                  100) if info["value"] else ""
            sub_info3 = "  start_time: %s\n," % info["start_time"].strftime(
                "%Y-%m-%d %H:%M:%S"
            ) if "start_time" in info and info["start_time"] else ""
            sub_info4 = "  history_profit: %g,  history_commission: %g,  history_profit_rate: %g%%," % (
                info["history_profit"], info["history_commission"],
                (info["history_profit"] * 100 / self.value))

            self.log_info(
                "symbol( %s ); current price( %g ); position(%s%s%s%s  total_profit_rate: %g%%)"
                %
                (symbol, cur_price, sub_info1, sub_info2, sub_info3, sub_info4,
                 (total_profit / self.value) * 100))
        # print(info)
        return info
예제 #9
0
    def analyze(self, symbol, orders):

        i = 1
        amount = 0
        value = 0
        commission = 0
        target_coin, base_coin = xq.get_symbol_coins(symbol)
        print(
            "  id          create_time  side  pst_rate   cur_price  deal_amount  deal_value      amount       value  commission      profit  profit_rate  rmk"
        )
        for order in orders:
            cur_price = order["deal_value"] / order["deal_amount"]
            if order["side"] == xq.SIDE_BUY:
                amount += order["deal_amount"]
                value += order["deal_value"]
            else:
                amount -= order["deal_amount"]
                value -= order["deal_value"]

            commission += order["deal_value"] * self.config["commission_rate"]

            amount = ts.reserve_float(amount, self.config["digits"][target_coin])
            profit = cur_price * amount - value - commission
            profit_rate = profit / self.config["limit"]["value"]

            print(
                "%4d  %s  %4s  %8g  %10g  %11g  %10g  %10g  %10g  %10g  %10g  %10.2f%%  %s"
                % (
                    i,
                    datetime.fromtimestamp(order["create_time"]),
                    order["side"],
                    order["pst_rate"],
                    cur_price,
                    order["deal_amount"],
                    order["deal_value"],
                    amount,
                    value,
                    commission,
                    profit,
                    round(profit_rate * 100, 2),
                    order["rmk"],
                )
            )
            i += 1
예제 #10
0
    def _get_position(self, symbol, orders, cur_price):
        info = {
            "amount": 0,  # 数量
            "price": 0,  # 平均价格,不包含佣金
            "cost_price": 0,  # 分摊佣金后的成本价
            "value": 0,  # 金额
            "commission": 0,  # 佣金
            "profit": 0,  # 当前利润
            "history_profit": 0,  # 历史利润
            "history_commission": 0,  # 历史佣金
            "start_time": None,  # 本周期第一笔买入时间
            "pst_rate": 0,  # 本次交易完成后要达到的持仓率
        }
        target_coin, base_coin = xq.get_symbol_coins(symbol)

        for order in orders:
            deal_amount = order["deal_amount"]
            deal_value = order["deal_value"]
            commission = deal_value * self.config["commission_rate"]

            if order["side"] == xq.SIDE_BUY:
                if info["amount"] == 0:
                    info["start_time"] = datetime.fromtimestamp(order["create_time"])

                info["amount"] += deal_amount
                info["value"] += deal_value
                info["commission"] += commission

            elif order["side"] == xq.SIDE_SELL:
                info["amount"] -= deal_amount
                info["value"] -= deal_value
                info["commission"] += commission
            else:
                logging.error("错误的委托方向")
                continue

            info["amount"] = ts.reserve_float(info["amount"], self.config["digits"][target_coin])

            if info["amount"] == 0:
                info["history_profit"] -= info["value"] + info["commission"]
                info["history_commission"] += info["commission"]
                info["value"] = 0
                info["commission"] = 0
                info["start_time"] = None

        if info["amount"] == 0:
            pass
        elif info["amount"] > 0:
            info["profit"] = (
                cur_price * info["amount"] - info["value"] - info["commission"]
            )
            info["price"] = info["value"] / info["amount"]
            info["cost_price"] = (info["value"] + info["commission"]) / info["amount"]

        else:
            logging.error("持仓数量不可能小于0")

        info["limit_base_amount"] = self.config["limit"]["value"]
        if orders:
            info["pst_rate"] = orders[-1]["pst_rate"]

        logging.info(
            "symbol( %s ); current price( %g ); position(%s%s%s  history_profit: %g,  history_commission: %g,  total_profit_rate: %g)",
            symbol,
            cur_price,
            "amount: %g,  price: %g, cost price: %g,  value: %g,  commission: %g,  limit: %g,  profit: %g,"
            % (
                info["amount"],
                info["price"],
                info["cost_price"],
                info["value"],
                info["commission"],
                info["limit_base_amount"],
                info["profit"],
            )
            if info["amount"]
            else "",
            "  profit rate: %g,"
            % (info["profit"] / (info["value"] + info["commission"]))
            if info["value"]
            else "",
            "  start_time: %s\n," % info["start_time"].strftime("%Y-%m-%d %H:%M:%S")
            if info["start_time"]
            else "",
            info["history_profit"],
            info["history_commission"],
            (info["profit"] + info["history_profit"]) / info["limit_base_amount"],
        )
        # print(info)
        return info
예제 #11
0
    def handle_order(self, symbol, cur_price, check_signals):
        """ 处理委托 """
        position_info = self.get_position(symbol, cur_price)

        rc_signals = self.risk_control(position_info, cur_price)
        if xq.SIDE_BUY in rc_signals:
            logging.warning("风控方向不能为买")
            return

        signals = rc_signals + check_signals
        if not signals:
            return

        logging.info("signals(%r)", signals)
        dcs_side, dcs_pst_rate, dcs_rmk, dcs_cba = xq.decision_signals2(signals)
        logging.info(
            "decision signal side(%s), position rate(%g), rmk(%s), can buy after(%s)",
            dcs_side,
            dcs_pst_rate,
            dcs_rmk,
            dcs_cba,
        )

        if dcs_side is None:
            return

        if self.can_buy_time:
            if self.now() < self.can_buy_time:
                # 时间范围之内,只能卖,不能买
                if dcs_side != xq.SIDE_SELL:
                    return
            else:
                # 时间范围之外,恢复
                self.can_buy_time = None

        if dcs_cba:
            if not self.can_buy_time or (self.can_buy_time and self.can_buy_time < self.now() + dcs_cba):
                self.can_buy_time = self.now() + dcs_cba
                logging.info("can buy time: %s", self.can_buy_time)

        if dcs_pst_rate > 1 or dcs_pst_rate < 0:
            logging.warning("仓位率(%g)超出范围(0 ~ 1)", dcs_pst_rate)
            return

        limit_mode = self.config["limit"]["mode"]
        limit_value = self.config["limit"]["value"]
        if limit_mode == 0:
            pass
        elif limit_mode == 1:
            limit_value += position_info["history_profit"]
        else:
            logging("请选择额度模式,默认是0")

        target_coin, base_coin = xq.get_symbol_coins(symbol)
        if dcs_side == xq.SIDE_BUY:
            if position_info["pst_rate"] >= dcs_pst_rate:
                return

            buy_base_amount = (
                limit_value * dcs_pst_rate
                - position_info["value"]
                - position_info["commission"]
            )
            if buy_base_amount <= 0:
                return

            base_balance = self.get_balances(base_coin)
            logging.info("base   balance:  %s", base_balance)

            buy_base_amount = min(xq.get_balance_free(base_balance), buy_base_amount)
            logging.info("buy_base_amount: %g", buy_base_amount)
            if buy_base_amount <= 0:  #
                return

            target_amount = ts.reserve_float(
                buy_base_amount / (cur_price * (1 + self.config["commission_rate"])),
                self.config["digits"][target_coin],
            )

            rate = 1.1

        elif dcs_side == xq.SIDE_SELL:
            if position_info["pst_rate"] <= dcs_pst_rate:
                return

            target_amount = ts.reserve_float(
                position_info["amount"]
                * (position_info["pst_rate"] - dcs_pst_rate)
                / position_info["pst_rate"],
                self.config["digits"][target_coin],
            )

            rate = 0.9
        else:
            return

        logging.info("%s target amount: %g" % (dcs_side, target_amount))
        if target_amount <= 0:
            return
        limit_price = ts.reserve_float(cur_price * rate, self.config["digits"][base_coin])
        order_id = self.send_order_limit(
            dcs_side,
            symbol,
            dcs_pst_rate,
            cur_price,
            limit_price,
            target_amount,
            "%s, timedelta: %s, can buy after: %s" % (dcs_rmk, dcs_cba, self.can_buy_time) if (dcs_cba or self.can_buy_time) else "%s" % (dcs_rmk),
        )
        logging.info(
            "current price: %g;  rate: %g;  order_id: %s", cur_price, rate, order_id
        )
예제 #12
0
 def __trans_symbol(self, symbol):
     """转换为binance格式的symbol"""
     target_coin, base_coin = xq.get_symbol_coins(symbol)
     return '%s%s' % (self.__get_coinkey(target_coin), self.__get_coinkey(base_coin))
예제 #13
0
 def __trans_symbol(self, symbol):
     target_coin, base_coin = xq.get_symbol_coins(symbol)
     return '%s_%s' % (self.__get_coinkey(target_coin), self.__get_coinkey(base_coin))
예제 #14
0
파일: engine.py 프로젝트: leezizi/xquant
    def send_order(self, symbol, position_info, cur_price, direction, action,
                   pst_rate, stop_loss_price, rmk):
        limit_price_rate = self.config["limit_price_rate"]
        limit_mode = self.config["mode"]
        limit_value = self.value
        if limit_mode == 0:
            pass
        elif limit_mode == 1:
            limit_value += position_info["history_profit"]
        else:
            self.log_error("请选择额度模式,默认是0")

        target_coin, base_coin = xq.get_symbol_coins(symbol)

        if action == bl.OPEN_POSITION:
            # 开仓
            if "pst_rate" in position_info and position_info[
                    "pst_rate"] >= pst_rate:
                return

            if position_info[POSITON_AMOUNT_KEY] == 0:
                pst_cost = 0
            else:
                pst_cost = abs(
                    position_info["value"]) + position_info["commission"]
            base_amount = limit_value * pst_rate - pst_cost
            if base_amount <= 0:
                return

            if direction == bl.DIRECTION_LONG:
                # 做多开仓
                '''
                base_balance = self.get_balances(base_coin)
                self.log_info("base   balance:  %s" % base_balance)
                base_amount = min(xq.get_balance_free(base_balance), base_amount)
                '''
                self.log_info("base_amount: %g" % base_amount)
                if base_amount <= 0:  #
                    return
                target_amount = base_amount / (
                    cur_price * (1 + self.config["commission_rate"]))
                rate = 1 + limit_price_rate["open"]
            else:
                # 做空开仓
                '''
                target_balance = self.get_balances(target_coin)
                self.log_info("target balance:  %s" % target_balance)
                # target_amount = min(xq.get_balance_free(target_balance), base_amount / cur_price)
                '''
                target_amount = base_amount / cur_price
                self.log_info("target_amount: %g" % target_amount)
                if target_amount <= 0:  #
                    return
                rate = 1 - limit_price_rate["open"]
        else:
            # 平仓
            if (not "pst_rate"
                    in position_info) or position_info["pst_rate"] <= pst_rate:
                return

            target_amount = abs(position_info["amount"]) * (
                position_info["pst_rate"] -
                pst_rate) / position_info["pst_rate"]

            if direction == bl.DIRECTION_LONG:
                # 做多平仓
                rate = 1 - limit_price_rate["close"]
            else:
                # 做空平仓
                rate = 1 + limit_price_rate["close"]

        target_amount = ts.reserve_float(target_amount,
                                         self.config["digits"][target_coin])
        self.log_info("%s %s target amount: %g" %
                      (direction, action, target_amount))
        if target_amount <= 0:
            return
        limit_price = ts.reserve_float(cur_price * rate,
                                       self.config["digits"][base_coin])
        order_id = self.send_order_limit(
            direction,
            action,
            symbol,
            pst_rate,
            cur_price,
            limit_price,
            target_amount,
            stop_loss_price,
            rmk,
        )
        self.log_info("current price: %g;  rate: %g;  order_id: %s" %
                      (cur_price, rate, order_id))
예제 #15
0
파일: engine.py 프로젝트: xiebing77/xquant
    def send_order(self, symbol, position_info, cur_price, direction, action,
                   pst_rate, stop_loss_price, rmk):
        limit_price_rate = self.config["limit_price_rate"]
        limit_mode = self.config["mode"]
        limit_value = self.value
        if limit_mode == 0:
            pass
        elif limit_mode == 1:
            limit_value += position_info["history_profit"]
        else:
            self.log_error("请选择额度模式,默认是0")

        limit_rate = limit_price_rate["default"]
        target_coin, base_coin = xq.get_symbol_coins(symbol)

        if action == bl.OPEN_POSITION:
            # 开仓

            if pst_is_lock(position_info):
                # 需要解锁动作
                if True:  # 同一账户
                    # 实际持仓已经为空,需发起1笔委托来新增持仓
                    action = bl.UNLOCK_POSITION
                    target_amount = position_info["lock_amount"]

                else:  # 不同账户
                    # 暂不实现
                    return
            else:
                if "pst_rate" in position_info and position_info[
                        "pst_rate"] >= pst_rate:
                    return

                if position_info[POSITON_AMOUNT_KEY] == 0:
                    pst_cost = 0
                else:
                    pst_cost = abs(
                        position_info["value"]) + position_info["commission"]
                base_amount = limit_value * pst_rate - pst_cost
                if base_amount <= 0:
                    return

                if direction == bl.DIRECTION_LONG:
                    # 做多开仓
                    '''
                    base_balance = self.get_balances(base_coin)
                    self.log_info("base   balance:  %s" % base_balance)
                    base_amount = min(xq.get_balance_free(base_balance), base_amount)
                    '''
                    self.log_info("base_amount: %g" % base_amount)
                    if base_amount <= 0:  #
                        return
                    target_amount = base_amount / (
                        cur_price * (1 + self.config["commission_rate"]))
                    rate = 1 + limit_price_rate["open"]
                else:
                    # 做空开仓
                    '''
                    target_balance = self.get_balances(target_coin)
                    self.log_info("target balance:  %s" % target_balance)
                    # target_amount = min(xq.get_balance_free(target_balance), base_amount / cur_price)
                    '''
                    target_amount = base_amount / cur_price
                    self.log_info("target_amount: %g" % target_amount)
                    if target_amount <= 0:  #
                        return
                    rate = 1 - limit_price_rate["open"]

        elif action == bl.CLOSE_POSITION:
            # 平仓
            if pst_is_lock(position_info):
                # 需要解锁和平仓2个动作
                if True:  # 同一账户
                    # 实际持仓已经为空,不需发起委托,但本次持仓结束
                    self.set_pst_lock_to_close(symbol, rmk)
                    return
                else:  # 不同账户
                    # 需要发起2笔委托,暂不实现
                    return
            else:
                if (not "pst_rate" in position_info
                    ) or position_info["pst_rate"] <= pst_rate:
                    return
                target_amount = abs(position_info["amount"]) * (
                    position_info["pst_rate"] -
                    pst_rate) / position_info["pst_rate"]
                if direction == bl.DIRECTION_LONG:
                    # 做多平仓
                    rate = 1 - limit_price_rate["close"]
                else:
                    # 做空平仓
                    rate = 1 + limit_price_rate["close"]

        elif action == bl.LOCK_POSITION:
            # 锁仓
            if pst_is_lock(position_info):  # 已经锁仓
                return

            if (not "pst_rate" in position_info
                ) or position_info["pst_rate"] <= 0:  # 没有仓位
                return

            target_amount = position_info[POSITON_AMOUNT_KEY]
            if direction == bl.DIRECTION_LONG:
                rate = 1 - limit_rate
            else:
                rate = 1 + limit_rate

        elif action == bl.UNLOCK_POSITION:
            # 解锁仓
            if not pst_is_lock(position_info):  # 没有锁仓
                return
            target_amount = position_info[LOCK_POSITON_AMOUNT_KEY]
            if direction == bl.DIRECTION_LONG:
                rate = 1 + limit_rate
            else:
                rate = 1 - limit_rate
        else:
            return

        target_amount = ts.reserve_float(target_amount,
                                         self.config["digits"][target_coin])
        self.log_info("%s %s target amount: %g" %
                      (direction, action, target_amount))
        if target_amount <= 0:
            return
        limit_price = ts.reserve_float(cur_price * rate,
                                       self.config["digits"][base_coin])
        order_id = self.send_order_limit(
            direction,
            action,
            symbol,
            pst_rate,
            cur_price,
            limit_price,
            target_amount,
            stop_loss_price,
            rmk,
        )
        self.log_info("current price: %g;  rate: %g;  order_id: %s" %
                      (cur_price, rate, order_id))
예제 #16
0
    def handle_order(self, symbol, position_info, cur_price, check_signals):
        """ 处理委托 """
        rc_signals = self.risk_control(position_info, cur_price)
        signals = rc_signals + check_signals
        if not signals:
            return
        for signal in signals:
            self.log_info("signal(%r)" % signal["describe"])

        ds_signal = xq.decision_signals(signals)
        self.log_info(
            "decision signal (%s  %s), position rate(%g), describe(%s), can buy after(%s)"
            % (ds_signal["direction"], ds_signal["action"],
               ds_signal["pst_rate"], ds_signal["describe"],
               ds_signal["can_open_time"]))

        if ds_signal["action"] is None:
            return

        if self.can_open_time:
            if self.now() < self.can_open_time:
                # 限定的时间范围内,只能平仓,不能开仓
                if ds_signal["action"] != xq.CLOSE_POSITION:
                    return
            else:
                # 时间范围之外,恢复
                self.can_open_time = None

        if ds_signal["can_open_time"]:
            if not self.can_open_time or (self.can_open_time
                                          and self.can_open_time < self.now() +
                                          ds_signal["can_open_time"]):
                self.can_open_time = self.now() + ds_signal["can_open_time"]
                self.log_info("can buy time: %s" % self.can_open_time)

        if ds_signal["pst_rate"] > 1 or ds_signal["pst_rate"] < 0:
            self.log_warning("仓位率(%g)超出范围(0 ~ 1)" % ds_signal["pst_rate"])
            return

        limit_price_rate = self.config["limit_price_rate"]
        limit_mode = self.config["mode"]
        limit_value = self.value
        if limit_mode == 0:
            pass
        elif limit_mode == 1:
            limit_value += position_info["history_profit"]
        else:
            self.log_error("请选择额度模式,默认是0")

        target_coin, base_coin = xq.get_symbol_coins(symbol)

        if ds_signal["action"] == xq.OPEN_POSITION:
            # 开仓
            if "pst_rate" in position_info and position_info[
                    "pst_rate"] >= ds_signal["pst_rate"]:
                return

            pst_cost = abs(
                position_info["value"]) + position_info["commission"]
            base_amount = limit_value * ds_signal["pst_rate"] - pst_cost
            if base_amount <= 0:
                return

            if ds_signal["direction"] == xq.DIRECTION_LONG:
                # 做多开仓
                base_balance = self.get_balances(base_coin)
                self.log_info("base   balance:  %s" % base_balance)
                base_amount = min(xq.get_balance_free(base_balance),
                                  base_amount)
                self.log_info("base_amount: %g" % base_amount)
                if base_amount <= 0:  #
                    return
                target_amount = base_amount / (
                    cur_price * (1 + self.config["commission_rate"]))
                rate = 1 + limit_price_rate["open"]
            else:
                # 做空开仓
                target_balance = self.get_balances(target_coin)
                self.log_info("target balance:  %s" % target_balance)
                target_amount = min(xq.get_balance_free(target_balance),
                                    base_amount / cur_price)
                self.log_info("target_amount: %g" % target_amount)
                if target_amount <= 0:  #
                    return
                rate = 1 - limit_price_rate["open"]
        else:
            # 平仓
            if (not "pst_rate" in position_info
                ) or position_info["pst_rate"] <= ds_signal["pst_rate"]:
                return

            target_amount = abs(position_info["amount"]) * (
                position_info["pst_rate"] -
                ds_signal["pst_rate"]) / position_info["pst_rate"]

            if ds_signal["direction"] == xq.DIRECTION_LONG:
                # 做多平仓
                rate = 1 - limit_price_rate["close"]
            else:
                # 做空平仓
                rate = 1 + limit_price_rate["close"]

        target_amount = ts.reserve_float(target_amount,
                                         self.config["digits"][target_coin])
        self.log_info(
            "%s %s target amount: %g" %
            (ds_signal["direction"], ds_signal["action"], target_amount))
        if target_amount <= 0:
            return
        limit_price = ts.reserve_float(cur_price * rate,
                                       self.config["digits"][base_coin])
        order_rmk = ds_signal["describe"] + ":  " + ds_signal["rmk"]
        order_id = self.send_order_limit(
            ds_signal["direction"],
            ds_signal["action"],
            symbol,
            ds_signal["pst_rate"],
            cur_price,
            limit_price,
            target_amount,
            "%s, timedelta: %s, can buy after: %s" %
            (order_rmk, ds_signal["can_open_time"], self.can_open_time) if
            (ds_signal["can_open_time"] or self.can_open_time) else "%s" %
            (order_rmk),
        )
        self.log_info("current price: %g;  rate: %g;  order_id: %s" %
                      (cur_price, rate, order_id))