def unlock_trade(self, password=None, password_md5=None, is_unlock=True):
        """
        交易解锁，安全考虑，所有的交易api,需成功解锁后才可操作
        :param password: 明文密码字符串 (二选一）
        :param password_md5: 密码的md5字符串（二选一）
        :param is_unlock: 解锁 = True, 锁定 = False
        :return:(ret, data) ret == RET_OK时, data为None，如果之前已经解锁过了，data为提示字符串，指示出已经解锁
                            ret != RET_OK时， data为错误字符串
        """

        # 仅支持真实交易的市场可以解锁，模拟交易不需要解锁
        md5_val = ''
        if is_unlock:
            ret = TRADE.check_mkt_envtype(self.__trd_mkt, TrdEnv.REAL)
            if not ret:
                return RET_OK, Err.NoNeedUnlock.text

            if password is None and password_md5 is None:
                return RET_ERROR, make_msg(Err.ParamErr, password=password, password_md5=password_md5)

            md5_val = str(password_md5) if password_md5 else md5_transform(str(password))

        # 解锁要求先拉一次帐户列表, 目前仅真实环境需要解锁
        ret, msg, acc_id = self._check_acc_id(TrdEnv.REAL, 0)
        if ret != RET_OK:
            return ret, msg

        query_processor = self._get_sync_query_processor(
                UnlockTrade.pack_req, UnlockTrade.unpack_rsp)

        kargs = {
            'is_unlock': is_unlock,
            'password_md5': md5_val,
            'conn_id': self.get_sync_conn_id()
        }

        ret_code, msg, _ = query_processor(**kargs)
        if ret_code != RET_OK:
            return RET_ERROR, msg

        # reconnected to auto unlock
        if RET_OK == ret_code:
            self._ctx_unlock = (password, password_md5) if is_unlock else None

        # 定阅交易帐号推送
        if is_unlock and ret_code == RET_OK:
            self.__check_acc_sub_push()

        if msg is not None and len(msg) > 0:
            return RET_OK, msg
        return RET_OK, None