def unsubscribe(self, code_list, subtype_list):
        """
        取消订阅
        :param code_list: 取消订阅的股票代码列表
        :param subtype_list: 取消订阅的类型，参见SubType
        :return: (ret, err_message)

                ret == RET_OK err_message为None

                ret != RET_OK err_message为错误描述字符串
        """

        ret, msg, code_list, subtype_list = self._check_subscribe_param(code_list, subtype_list)
        if ret != RET_OK:
            return ret, msg

        query_processor = self._get_sync_query_processor(SubscriptionQuery.pack_unsubscribe_req,
                                                         SubscriptionQuery.unpack_unsubscribe_rsp)

        kargs = {
            'code_list': code_list,
            'subtype_list': subtype_list,
            "conn_id": self.get_sync_conn_id()
        }

        for subtype in subtype_list:
            if subtype not in self._ctx_subscribe:
                continue
            code_set = self._ctx_subscribe[subtype]
            for code in code_list:
                if code not in code_set:
                    continue
                code_set.remove(code)

        ret_code, msg, _ = query_processor(**kargs)

        if ret_code != RET_OK:
            return RET_ERROR, msg

        ret_code, msg, unpush_req_str = SubscriptionQuery.pack_unpush_req(code_list, subtype_list, self.get_async_conn_id())
        if ret_code != RET_OK:
            return RET_ERROR, msg

        ret_code, msg = self._send_async_req(unpush_req_str)
        if ret_code != RET_OK:
            return RET_ERROR, msg

        return RET_OK, None
取消订阅
        :param code_list: 取消订阅的股票代码列表
        :param subtype_list: 取消订阅的类型，参见SubType
        :return: (ret, err_message)

                ret == RET_OK err_message为None

                ret != RET_OK err_message为错误描述字符串