Пример #1
0
 def get_ipo_limit(self, stock_code):
     """
     查询新股申购额度申购上限
     :param stock_code: 申购代码 ID
     :return:
     """
     logger.warning("目前仅在 佣金宝子类 中实现, 其余券商需要补充")
Пример #2
0
 def read_config(self, path):
     try:
         self.account_config = file2dict(path)
     except ValueError:
         logger.error("配置文件格式有误,请勿使用记事本编辑,推荐 sublime text")
     for value in self.account_config:
         if isinstance(value, int):
             logger.warning("配置文件的值最好使用双引号包裹,使用字符串,否则可能导致不可知问题")
Пример #3
0
 def get_exchangebill(self, start_date, end_date):
     """
     查询指定日期内的交割单
     :param start_date: 20160211
     :param end_date: 20160211
     :return:
     """
     logger.warning("目前仅在 华泰子类 中实现, 其余券商需要补充")
Пример #4
0
    def _trade(self, security, price=0, amount=0, volume=0, entrust_bs="buy"):
        """
        调仓
        :param security:
        :param price:
        :param amount:
        :param volume:
        :param entrust_bs:
        :return:
        """
        stock = self._search_stock_info(security)
        balance = self.get_balance()[0]
        if stock is None:
            raise exceptions.TradeError(u"没有查询要操作的股票信息")
        if not volume:
            volume = int(float(price) * amount)  # 可能要取整数
        if balance["current_balance"] < volume and entrust_bs == "buy":
            raise exceptions.TradeError(u"没有足够的现金进行操作")
        if stock["flag"] != 1:
            raise exceptions.TradeError(u"未上市、停牌、涨跌停、退市的股票无法操作。")
        if volume == 0:
            raise exceptions.TradeError(u"操作金额不能为零")

        # 计算调仓调仓份额
        weight = volume / balance["asset_balance"] * 100
        weight = round(weight, 2)

        # 获取原有仓位信息
        position_list = self._get_position()

        # 调整后的持仓
        is_have = False
        for position in position_list:
            if position["stock_id"] == stock["stock_id"]:
                is_have = True
                position["proactive"] = True
                old_weight = position["weight"]
                if entrust_bs == "buy":
                    position["weight"] = weight + old_weight
                else:
                    if weight > old_weight:
                        raise exceptions.TradeError(u"操作数量大于实际可卖出数量")
                    else:
                        position["weight"] = old_weight - weight
                position["weight"] = round(position["weight"], 2)
        if not is_have:
            if entrust_bs == "buy":
                position_list.append({
                    "code": stock["code"],
                    "name": stock["name"],
                    "enName": stock["enName"],
                    "hasexist": stock["hasexist"],
                    "flag": stock["flag"],
                    "type": stock["type"],
                    "current": stock["current"],
                    "chg": stock["chg"],
                    "percent": str(stock["percent"]),
                    "stock_id": stock["stock_id"],
                    "ind_id": stock["ind_id"],
                    "ind_name": stock["ind_name"],
                    "ind_color": stock["ind_color"],
                    "textname": stock["name"],
                    "segment_name": stock["ind_name"],
                    "weight": round(weight, 2),
                    "url": "/S/" + stock["code"],
                    "proactive": True,
                    "price": str(stock["current"]),
                })
            else:
                raise exceptions.TradeError(u"没有持有要卖出的股票")

        if entrust_bs == "buy":
            cash = ((balance["current_balance"] - volume) /
                    balance["asset_balance"] * 100)
        else:
            cash = ((balance["current_balance"] + volume) /
                    balance["asset_balance"] * 100)
        cash = round(cash, 2)
        logger.info("weight:%f, cash:%f", weight, cash)

        data = {
            "cash": cash,
            "holdings": str(json.dumps(position_list)),
            "cube_symbol": str(self.account_config["portfolio_code"]),
            "segment": 1,
            "comment": "",
        }

        try:
            resp = self.s.post(self.config["rebalance_url"], data=data)
        # pylint: disable=broad-except
        except Exception as e:
            logger.warning("调仓失败: %s ", e)
            return None
        else:
            logger.info("调仓 %s%s: %d", entrust_bs, stock["name"],
                        resp.status_code)
            resp_json = json.loads(resp.text)
            if "error_description" in resp_json and resp.status_code != 200:
                logger.error("调仓错误: %s", resp_json["error_description"])
                return [{
                    "error_no": resp_json["error_code"],
                    "error_info": resp_json["error_description"],
                }]
            return [{
                "entrust_no":
                resp_json["id"],
                "init_date":
                self._time_strftime(resp_json["created_at"]),
                "batch_no":
                "委托批号",
                "report_no":
                "申报号",
                "seat_no":
                "席位编号",
                "entrust_time":
                self._time_strftime(resp_json["updated_at"]),
                "entrust_price":
                price,
                "entrust_amount":
                amount,
                "stock_code":
                security,
                "entrust_bs":
                "买入",
                "entrust_type":
                "雪球虚拟委托",
                "entrust_status":
                "-",
            }]
Пример #5
0
    def adjust_weight(self, stock_code, weight):
        """
        雪球组合调仓, weight 为调整后的仓位比例
        :param stock_code: str 股票代码
        :param weight: float 调整之后的持仓百分比, 0 - 100 之间的浮点数
        """

        stock = self._search_stock_info(stock_code)
        if stock is None:
            raise exceptions.TradeError(u"没有查询要操作的股票信息")
        if stock["flag"] != 1:
            raise exceptions.TradeError(u"未上市、停牌、涨跌停、退市的股票无法操作。")

        # 仓位比例向下取两位数
        weight = round(weight, 2)
        # 获取原有仓位信息
        position_list = self._get_position()

        # 调整后的持仓
        for position in position_list:
            if position["stock_id"] == stock["stock_id"]:
                position["proactive"] = True
                position["weight"] = weight

        if weight != 0 and stock["stock_id"] not in [
                k["stock_id"] for k in position_list
        ]:
            position_list.append({
                "code": stock["code"],
                "name": stock["name"],
                "enName": stock["enName"],
                "hasexist": stock["hasexist"],
                "flag": stock["flag"],
                "type": stock["type"],
                "current": stock["current"],
                "chg": stock["chg"],
                "percent": str(stock["percent"]),
                "stock_id": stock["stock_id"],
                "ind_id": stock["ind_id"],
                "ind_name": stock["ind_name"],
                "ind_color": stock["ind_color"],
                "textname": stock["name"],
                "segment_name": stock["ind_name"],
                "weight": weight,
                "url": "/S/" + stock["code"],
                "proactive": True,
                "price": str(stock["current"]),
            })

        remain_weight = 100 - sum(i.get("weight") for i in position_list)
        cash = round(remain_weight, 2)
        logger.info("调仓比例:%f, 剩余持仓 :%f", weight, remain_weight)
        data = {
            "cash": cash,
            "holdings": str(json.dumps(position_list)),
            "cube_symbol": str(self.account_config["portfolio_code"]),
            "segment": "true",
            "comment": "",
        }

        try:
            resp = self.s.post(self.config["rebalance_url"], data=data)
        # pylint: disable=broad-except
        except Exception as e:
            logger.warning("调仓失败: %s ", e)
            return None
        logger.info("调仓 %s: 持仓比例%d", stock["name"], weight)
        resp_json = json.loads(resp.text)
        if "error_description" in resp_json and resp.status_code != 200:
            logger.error("调仓错误: %s", resp_json["error_description"])
            return [{
                "error_no": resp_json["error_code"],
                "error_info": resp_json["error_description"],
            }]
        logger.info("调仓成功 %s: 持仓比例%d", stock["name"], weight)
        return None
Пример #6
0
    def _execute_trade_cmd(self, trade_cmd, users, expire_seconds,
                           entrust_prop, send_interval):
        """分发交易指令到对应的 user 并执行
        :param trade_cmd:
        :param users:
        :param expire_seconds:
        :param entrust_prop:
        :param send_interval:
        :return:
        """
        for user in users:
            # check expire
            now = datetime.datetime.now()
            expire = (now - trade_cmd["datetime"]).total_seconds()
            if expire > expire_seconds:
                logger.warning(
                    "策略 [%s] 指令(股票: %s 动作: %s 数量: %s 价格: %s)超时,指令产生时间: %s 当前时间: %s, 超过设置的最大过期时间 %s 秒, 被丢弃",
                    trade_cmd["strategy_name"],
                    trade_cmd["stock_code"],
                    trade_cmd["action"],
                    trade_cmd["amount"],
                    trade_cmd["price"],
                    trade_cmd["datetime"],
                    now,
                    expire_seconds,
                )
                break

            # check price
            price = trade_cmd["price"]
            if not self._is_number(price) or price <= 0:
                logger.warning(
                    "策略 [%s] 指令(股票: %s 动作: %s 数量: %s 价格: %s)超时,指令产生时间: %s 当前时间: %s, 价格无效 , 被丢弃",
                    trade_cmd["strategy_name"],
                    trade_cmd["stock_code"],
                    trade_cmd["action"],
                    trade_cmd["amount"],
                    trade_cmd["price"],
                    trade_cmd["datetime"],
                    now,
                )
                break

            # check amount
            if trade_cmd["amount"] <= 0:
                logger.warning(
                    "策略 [%s] 指令(股票: %s 动作: %s 数量: %s 价格: %s)超时,指令产生时间: %s 当前时间: %s, 买入股数无效 , 被丢弃",
                    trade_cmd["strategy_name"],
                    trade_cmd["stock_code"],
                    trade_cmd["action"],
                    trade_cmd["amount"],
                    trade_cmd["price"],
                    trade_cmd["datetime"],
                    now,
                )
                break

            actual_price = self._calculate_price_by_slippage(
                trade_cmd["action"], trade_cmd["price"])
            args = {
                "security": trade_cmd["stock_code"],
                "price": actual_price,
                "amount": trade_cmd["amount"],
                "entrust_prop": entrust_prop,
            }
            try:
                response = getattr(user, trade_cmd["action"])(**args)
            except exceptions.TradeError as e:
                trader_name = type(user).__name__
                err_msg = "{}: {}".format(type(e).__name__, e.args)
                logger.error(
                    "%s 执行 策略 [%s] 指令(股票: %s 动作: %s 数量: %s 价格(考虑滑点): %s 指令产生时间: %s) 失败, 错误信息: %s",
                    trader_name,
                    trade_cmd["strategy_name"],
                    trade_cmd["stock_code"],
                    trade_cmd["action"],
                    trade_cmd["amount"],
                    actual_price,
                    trade_cmd["datetime"],
                    err_msg,
                )
            else:
                logger.info(
                    "策略 [%s] 指令(股票: %s 动作: %s 数量: %s 价格(考虑滑点): %s 指令产生时间: %s) 执行成功, 返回: %s",
                    trade_cmd["strategy_name"],
                    trade_cmd["stock_code"],
                    trade_cmd["action"],
                    trade_cmd["amount"],
                    actual_price,
                    trade_cmd["datetime"],
                    response,
                )
Пример #7
0
 def get_current_deal(self):
     """获取当日委托列表"""
     # return self.do(self.config['current_deal'])
     logger.warning("目前仅在 佣金宝/银河子类 中实现, 其余券商需要补充")