策略评价1:根据交易信号Signal,1.提取交易记录,2.绝对收益和相对收益,3.交易与不交易对比,4.收盘价最大回撤,5.资金最大回撤。6.可视化图形回测。

学习目标:根据交易信号Signal评估回测结果

学习内容:

df的格式要包含收盘价(Close),交易持仓信号(Signal)买入后为1,卖出后为-1
形式如下:df的xingshi

1:提取交易记录,和交易概览信息的统计。

# 交易概览信息的统计
def log_trade_info(stock_dat):

    signal_shift = stock_dat.Signal.shift(1)
    signal_shift.fillna(value=-1, inplace=True)  # 序列最前面的NaN值用-1填充
    list_signal = np.sign(stock_dat.Signal - signal_shift)
    #print(list_signal)

    buy_singal = stock_dat[list_signal.isin([1])]
    sell_singal = stock_dat[list_signal.isin([-1])]

    trade_info = pd.DataFrame({'BuyTime': buy_singal.index.strftime("%y.%m.%d"),
                               'SellTime': sell_singal.index.strftime("%y.%m.%d"),
                               'BuyPrice': buy_singal.Close.values,
                               'SellPrice': sell_singal.Close.values})

    trade_info['DiffPrice'] = trade_info.SellPrice - trade_info.BuyPrice
    trade_info['PctProfit'] = np.round(trade_info.DiffPrice/trade_info.BuyPrice*100, 2)

    win_count = (trade_info.DiffPrice >= 0).sum()
    loss_count = (trade_info.DiffPrice < 0).sum()
    win_profit = trade_info[trade_info.PctProfit >= 0].PctProfit.sum()
    loss_profit = trade_info[trade_info.PctProfit < 0].PctProfit.sum()
    print(f'亏损次数:{loss_count}, 盈利次数:{win_count}, 胜率:{round(win_count / (win_count + loss_count)*100, 2)}%')
    print(f'平均亏损:{round((loss_profit / loss_count), 2)}% 平均盈利:{round((win_profit / win_count), 2)}%')
    return trade_info
print(log_trade_info(df))

2:# 度量策略绝对收益和相对收益,初始资金100000,有滑点和手续费,df的格式要包含收盘价(Close),交易持仓信号(Signal)买入后为1,卖出后为-1。返回的df包含资金线(total)。

# 度量策略绝对收益和相对收益
def draw_absolute_profit(stock_dat):

    cash_hold = 100000 # 初始资金
    posit_num = 0 # 持股数目
    skip_days = False # 持股/持币状态
    slippage = 0.01 # 滑点,默认为0.01
    c_rate = 5.0 / 10000  # 手续费,commission,默认万分之5
    t_rate = 1.0 / 1000  # 印花税,tax,默认千分之1

    # 绝对收益—资金的度量
    for kl_index, today in stock_dat.iterrows():
        # 买入/卖出执行代码
        if today.Signal == 1 and skip_days == False: # 买入
            skip_days = True
            posit_num = int(cash_hold / (today.Close + slippage)) # 资金转化为股票
            posit_num = int(posit_num / 100) * 100 # 买入股票最少100股,对posit_num向下取整百
            buy_cash = posit_num * (today.Close + slippage) # 计算买入股票所需现金
            # 计算手续费,不足5元按5元收,并保留2位小数
            commission = round(max(buy_cash * c_rate, 5), 2)
            cash_hold = cash_hold - buy_cash - commission
        elif today.Signal == -1 and skip_days == True: # 卖出,避免未买先卖
            skip_days = False
            sell_cash = posit_num * (today.Close - slippage) # 计算卖出股票得到的现金 卖出股票可以不是整百。
            # 计算手续费,不足5元按5元收,并保留2位小数
            commission = round(max(sell_cash * c_rate, 5), 2)
            # 计算印花税,保留2位小数
            tax = round(sell_cash * t_rate, 2)
            cash_hold = cash_hold + sell_cash - commission - tax # 剩余现金
        if skip_days == True: # 持股
            stock_dat.loc[kl_index,'total'] = posit_num * today.Close+ cash_hold
        else: # 空仓
            stock_dat.loc[kl_index,'total'] = cash_hold

    line_key = "资金总体收益%d;上涨幅度 %.2f%%" % (stock_dat['total'][-1], (stock_dat['total'][-1] - 100000) / 100000*100)
    print(line_key)
    return stock_dat
print(draw_absolute_profit(df))

3:交易与不交易对比,df的格式要包含收盘价(Close),交易持仓信号(Signal)买入后为1,卖出后为-1。返回的df包含每日涨跌幅(trend_profit_pct)和波动的幅度(benchmark_profit_pct)。

def draw_relative_profit(stock_dat):
    # 相对收益—策略VS基准
    pct_close = stock_dat['Close'].pct_change()
    # 交易信号与股票每日涨跌幅相乘,即可得策略的每日涨跌幅,累乘后计算策略累计收益

    trend_profit_pct = (1 + stock_dat['Signal'] * pct_close).cumprod()
    # 把股票价格转换成从1开始,即波动的幅度

    benchmark_profit_pct = stock_dat['Close']/stock_dat['Close'][0]

    stock_dat['benchmark_profit_log'] = np.log(stock_dat.Close/stock_dat.Close.shift(1))
    stock_dat.loc[stock_dat.Signal == -1, 'Signal'] = 0
    stock_dat['trend_profit_log'] = stock_dat['Signal'] * stock_dat.benchmark_profit_log
    line_trend_key = "策略收益%.2f" % (stock_dat['trend_profit_log'].cumsum()[-1])
    line_bench_key = "基准收益%.2f" % (stock_dat['benchmark_profit_log'].cumsum()[-1])

    print("资金相对收益:%s VS %s" % (line_trend_key, line_bench_key))
    return stock_dat
print(draw_relative_profit(df))

4.度量策略最大风险回撤——收盘价最大回撤,df同上

def draw_closemax_risk(stock_dat):
    # 度量策略最大风险回撤——收盘价最大回撤

    # 计算收盘价曲线当前的滚动最高值
    stock_dat['max_close'] = stock_dat['Close'].expanding().max()
    # 计算收盘价曲线在滚动最高值之后所回撤的百分比
    stock_dat['per_close'] = stock_dat['Close'] / stock_dat['max_close']

    # 寻找出收盘价最大回撤率交易日
    min_point_df = stock_dat.sort_values(by=['per_close'])[0:1]
    min_point_close = min_point_df.per_close
    #min_point_close = stock_dat.sort_values(by=['per_close']).iloc[[0], stock_dat.columns.get_loc('per_close')]

    # 寻找出收盘价最高值交易日
    max_point_df = stock_dat[stock_dat.index <= min_point_close.index[0]].sort_values(by=['Close'], ascending=False)[0:1]
    max_point_close = max_point_df.Close
    #max_point_close = stock_dat[stock_dat.index <= min_point_close.index[0]].sort_values \
    #    (by=['Close'], ascending=False).iloc[[0], stock_dat.columns.get_loc('Close')]

    # 打印收盘价的最大回撤率与所对应的最高值交易日和最大回撤交易日
    print("股价最大回撤%5.2f%% 从%s开始至%s结束" % ((1 - min_point_close.values)*100,\
                                        max_point_close.index[0], min_point_close.index[0]))
    return stock_dat
print(draw_closemax_risk(get_trade_signal(pro_daily_stock("000651.SZ", '20180601', '20190601'))))

5.度量策略最大风险回撤——资金最大回撤,df同上

def draw_profitmax_risk(stock_dat):
    # 度量策略最大风险回撤——资金最大回撤
    cash_hold = 100000 # 初始资金
    posit_num = 0 # 持股数目
    skip_days = False # 持股/持币状态
    slippage = 0.01 # 滑点,默认为0.01
    c_rate = 5.0 / 10000  # 手续费,commission,默认万分之5
    t_rate = 1.0 / 1000  # 印花税,tax,默认千分之1

    # 绝对收益—资金的度量
    for kl_index, today in stock_dat.iterrows():
        # 买入/卖出执行代码
        if today.Signal == 1 and skip_days == False: #买入
            skip_days = True
            posit_num = int(cash_hold / (today.Close + slippage)) # 资金转化为股票
            posit_num = int(posit_num / 100) * 100  # 买入股票最少100股,对posit_num向下取整百
            buy_cash = posit_num * (today.Close + slippage) # 计算买入股票所需现金
            # 计算手续费,不足5元按5元收,并保留2位小数
            commission = round(max(buy_cash * c_rate, 5), 2)
            cash_hold = cash_hold - buy_cash - commission

        elif today.Signal == -1 and skip_days == True: # 卖出 避免未买先卖
            skip_days = False
            sell_cash = posit_num * (today.Close - slippage) # 计算卖出股票得到的现金 卖出股票可以不是整百。
            # 计算手续费,不足5元按5元收,并保留2位小数
            commission = round(max(sell_cash * c_rate, 5), 2)
            # 计算印花税,保留2位小数
            tax = round(sell_cash * t_rate, 2)
            cash_hold = cash_hold + sell_cash - commission - tax # 剩余现金

        if skip_days == True: # 持股
            stock_dat.loc[kl_index,'total'] = posit_num * today.Close + cash_hold
        else: # 空仓
            stock_dat.loc[kl_index,'total'] = cash_hold

        # expanding()计算资金曲线当前的滚动最高值
        stock_dat['max_total'] = stock_dat['total'].expanding().max()

        # 计算资金曲线在滚动最高值之后所回撤的百分比
        stock_dat['per_total'] = stock_dat['total'] / stock_dat['max_total']

    min_point_df = stock_dat.sort_values(by=['per_total'])[0:1]
    min_point_total = min_point_df.per_total
    max_point_df = stock_dat[stock_dat.index <= min_point_total.index[0]].sort_values(by=['total'], ascending=False)[0:1]
    max_point_total = max_point_df.total
    #min_point_total = stock_dat.sort_values(by=['per_total']).iloc[[0], stock_dat.columns.get_loc('per_total')]
    #max_point_total = stock_dat[stock_dat.index <= min_point_total.index[0]].sort_values \
    #    (by=['total'], ascending=False).iloc[[0], stock_dat.columns.get_loc('total')]

    print("资金最大回撤%5.2f%% 从%s开始至%s结束" % ((1 - min_point_total.values)*100, \
                                       max_point_total.index[0], min_point_total.index[0]))
    return stock_dat
    # 最大资金回撤 7.49%从2018-07-13 00:00:00开始至2018-09-12 00:00:00结束
print(draw_profitmax_risk(df))

6.回测界面化一体程序,df如上(只需改动函数最后一行的df)

class MultiTraceIf(MplTypesDraw):

    app = DefTypesPool()
    ##########################回测分析界面###############################
    @app.route_types(u"cash_profit")# cash profit and retracement
    def cash_profit_graph(stock_dat, sub_graph, cash_hold = 100000,
                                                slippage = 0.01,
                                                c_rate = 5.0 / 10000,
                                                t_rate = 1.0 / 1000):
        posit_num = 0  # 持股数目
        skip_days = False  # 持股/持币状态

        # 最大风险回撤——资金最大回撤
        # 绝对收益—资金的度量
        for kl_index, today in stock_dat.iterrows():
            # 买入/卖出执行代码
            if today.Signal == 1 and skip_days == False:  # 买入
                skip_days = True
                posit_num = int(cash_hold / (today.Close + slippage))  # 资金转化为股票
                posit_num = int(posit_num / 100) * 100  # 买入股票最少100股,对posit_num向下取整百
                buy_cash = posit_num * (today.Close + slippage)  # 计算买入股票所需现金
                # 计算手续费,不足5元按5元收,并保留2位小数
                commission = round(max(buy_cash * c_rate, 5), 2)
                cash_hold = cash_hold - buy_cash - commission

            elif today.Signal == -1 and skip_days == True:  # 卖出 避免未买先卖
                skip_days = False
                sell_cash = posit_num * (today.Close - slippage) # 计算卖出股票得到的现金 卖出股票可以不是整百。
                # 计算手续费,不足5元按5元收,并保留2位小数
                commission = round(max(sell_cash * c_rate, 5), 2)
                # 计算印花税,保留2位小数
                tax = round(sell_cash * t_rate, 2)
                cash_hold = cash_hold + sell_cash - commission - tax # 剩余现金
            if skip_days == True:  # 持股
                stock_dat.loc[kl_index, 'total'] = posit_num * today.Close + cash_hold
            else:  # 空仓
                stock_dat.loc[kl_index, 'total'] = cash_hold

            # expanding()计算资金曲线当前的滚动最高值
            stock_dat['max_total'] = stock_dat['total'].expanding().max()
            # 计算资金曲线在滚动最高值之后所回撤的百分比
            stock_dat['per_total'] = stock_dat['total'] / stock_dat['max_total']

        min_point_df = stock_dat.sort_values(by=['per_total'])[0:1]
        min_point_total = min_point_df.per_total
        max_point_df = stock_dat[stock_dat.index <= min_point_total.index[0]].sort_values(by=['total'],
                                                                                          ascending=False)[0:1]
        max_point_total = max_point_df.total
        # min_point_total = stock_dat.sort_values(by=['per_total']).iloc[[0], stock_dat.columns.get_loc('per_total')]
        # max_point_total = stock_dat[stock_dat.index <= min_point_total.index[0]].sort_values \
        #    (by=['total'], ascending=False).iloc[[0], stock_dat.columns.get_loc('total')]

        print("资金最大回撤%5.2f%% 从%s开始至%s结束" % ((1 - min_point_total.values) * 100, \
                                            max_point_total.index[0], min_point_total.index[0]))
        # 最大资金回撤 7.53%从2018-07-13 00:00:00开始至2018-09-12 00:00:00结束

        line_total = "资金总体收益%d;上涨幅度 %.2f%%" % (stock_dat['total'][-1], (stock_dat['total'][-1] - 100000) / 100000 * 100)
        print(line_total)
        max_total = "资金滚动最高值"

        type_dict = {line_total: stock_dat.total,
                     max_total: stock_dat.max_total,
                     }
        view_function = MplTypesDraw.mpl.route_output(u"line")
        view_function(stock_dat.index, type_dict, sub_graph)

        type_dict = {u"资金最大回撤\n{}".format(1 - min_point_total.values):
                         {'andata': min_point_df,
                          'va': 'top',
                          'xy_y': 'total',
                          'xytext': (0,stock_dat['High'].mean()),
                          'fontsize': 8,
                          'arrow': dict(facecolor='green', shrink=0.1)
                          },
                      }
        view_function = MplTypesDraw.mpl.route_output(u"annotate")
        view_function(stock_dat.index, type_dict, sub_graph)

    @app.route_types(u"cmp_profit")  # relative_profit
    def cmp_profit_graph(stock_dat, sub_graph, para_dat):

        # 相对收益—策略VS基准
        stock_dat['benchmark_profit_log'] = np.log(stock_dat.Close / stock_dat.Close.shift(1))
        stock_dat.loc[stock_dat.Signal == -1, 'Signal'] = 0
        stock_dat['trend_profit_log'] = stock_dat['Signal'] * stock_dat.benchmark_profit_log
        line_trend_key = "策略收益%.2f" % stock_dat['trend_profit_log'].cumsum()[-1]
        line_bench_key = "基准收益%.2f" % stock_dat['benchmark_profit_log'].cumsum()[-1]
        print("资金相对收益:%s VS %s" % (line_trend_key, line_bench_key))

        type_dict = {line_bench_key: stock_dat['benchmark_profit_log'].cumsum(),
                     line_trend_key: stock_dat['trend_profit_log'].cumsum()
                     }
        view_function = MplTypesDraw.mpl.route_output(u"line")
        view_function(stock_dat.index, type_dict, sub_graph)

    @app.route_types(u"close_retrace")  # relative_profit
    def close_retrace_graph(stock_dat, sub_graph, para_dat):
        # 度量策略最大风险回撤——收盘价最大回撤

        # 计算收盘价曲线当前的滚动最高值
        stock_dat['max_close'] = stock_dat['Close'].expanding().max()
        # 计算收盘价曲线在滚动最高值之后所回撤的百分比
        stock_dat['per_close'] = stock_dat['Close'] / stock_dat['max_close']

        # 计算并打印收盘价的最大回撤率
        min_point_df = stock_dat.sort_values(by=['per_close'])[0:1]
        min_point_close = min_point_df.per_close
        # min_point_close = stock_dat.sort_values(by=['per_close']).iloc[[0], stock_dat.columns.get_loc('per_close')]

        # 寻找出最大回撤率所对应的最高值交易日和最大回撤交易日,并打印显示
        max_point_df = stock_dat[stock_dat.index <= min_point_close.index[0]].sort_values(by=['Close'],
                                                                                          ascending=False)[0:1]
        max_point_close = max_point_df.Close
        # max_point_close = stock_dat[stock_dat.index <= min_point_close.index[0]].sort_values \
        #    (by=['Close'], ascending=False).iloc[[0], stock_dat.columns.get_loc('Close')]

        print("股价最大回撤%5.2f%% 从%s开始至%s结束" % ((1 - min_point_close.values) * 100, \
                                            max_point_close.index[0], min_point_close.index[0]))
        ##最大股价回撤 29.21% 从2018-06-12 00:00:00开始至2018-12-27 00:00:00结束

        type_dict = {'最大收盘价': stock_dat.max_close,
                     '收盘价': stock_dat.Close
                     }
        view_function = MplTypesDraw.mpl.route_output(u"line")
        view_function(stock_dat.index, type_dict, sub_graph)

        type_dict = {u"股价最大回撤\n{}".format(1 - min_point_close.values):
                               {'andata': min_point_df,
                                'va': 'top',
                                'xy_y': 'Close',
                                'xytext': (0,stock_dat['High'].mean()),
                                'fontsize': 8,
                                'arrow': dict(facecolor='green', shrink=0.1)
                                },
                    }
        view_function = MplTypesDraw.mpl.route_output(u"annotate")
        view_function(stock_dat.index, type_dict, sub_graph)

    @app.route_types(u"trade")
    def trade_graph(stock_dat, sub_graph, para_dat):
        # 交易获利/亏损区间可视化

        type_dict = {'signal': stock_dat.Signal,
                     'jdval': stock_dat.Close,
                     'va': 'top',
                     'xy_y': 'Close',
                     'xytext': (0,stock_dat['High'].mean()),
                     'fontsize': 8,
                     'arrow': dict(facecolor='yellow', shrink=0.1)
                     }
        view_function = MplTypesDraw.mpl.route_output(u"filltrade")
        view_function(stock_dat.index, type_dict, sub_graph)

    def __init__(self, **kwargs):
        MplTypesDraw.__init__(self)
        self.fig = plt.figure(figsize=kwargs['figsize'], dpi=100, facecolor="white")#创建fig对象
        self.graph_dict = {}
        self.graph_curr = []

        try:
            gs = gridspec.GridSpec(kwargs['nrows'], kwargs['ncols'],
                                   left = kwargs['left'], bottom = kwargs['bottom'], right = kwargs['right'], top = kwargs['top'],
                                   wspace = kwargs['wspace'], hspace = kwargs['hspace'], height_ratios = kwargs['height_ratios'])
        except:
            raise Exception("para error")
        else:
            for i in range(0, kwargs['nrows'], 1):
                self.graph_dict[kwargs['subplots'][i]] = self.fig.add_subplot(gs[i, :])

    def log_trade_info(self, stock_dat):

        signal_shift = stock_dat.Signal.shift(1)
        signal_shift.fillna(value=-1, inplace=True)  # 序列最前面的NaN值用-1填充
        list_signal = np.sign(stock_dat.Signal - signal_shift)

        buy_singal = stock_dat[list_signal.isin([1])]
        sell_singal = stock_dat[list_signal.isin([-1])]

        trade_info = pd.DataFrame({'BuyTime': buy_singal.index.strftime("%y.%m.%d"),
                                   'SellTime': sell_singal.index.strftime("%y.%m.%d"),
                                   'BuyPrice': buy_singal.Close.values,
                                   'SellPrice': sell_singal.Close.values})

        trade_info['DiffPrice'] = trade_info.SellPrice - trade_info.BuyPrice
        trade_info['PctProfit'] = np.round(trade_info.DiffPrice / trade_info.BuyPrice*100, 2)

        win_count = (trade_info.DiffPrice >= 0).sum()
        loss_count = (trade_info.DiffPrice < 0).sum()
        win_profit = trade_info[trade_info.PctProfit >= 0].PctProfit.sum()
        loss_profit = trade_info[trade_info.PctProfit < 0].PctProfit.sum()

        print(trade_info)
        print(f'亏损次数:{loss_count}, 盈利次数:{win_count}, 胜率:{round(win_count / (win_count + loss_count)*100, 2)}%')
        print(f'平均亏损:{round((loss_profit / loss_count), 2)}% 平均盈利:{round((win_profit / win_count), 2)}%')

    def graph_run(self, stock_data, **kwargs):
        # 绘制子图
        self.df_ohlc = stock_data

        # 临时把标准输出重定向到一个文件,然后再恢复正常
        with open('logtrade.txt', 'w') as f:
            oldstdout = sys.stdout
            sys.stdout = f
            try:
                self.log_trade_info(self.df_ohlc)
                for key in kwargs:
                    self.graph_curr = self.graph_dict[kwargs[key]['graph_name']]
                    for path, val in kwargs[key]['graph_type'].items():
                        view_function = MultiTraceIf.app.route_output(path)
                        view_function(self.df_ohlc, self.graph_curr, val)
                    self.graph_attr(**kwargs[key])
                plt.show()
            finally:
                sys.stdout = oldstdout

        """
        print("kwargs %s-->%s" % (key, kwargs[key]))
        #globals().get('self.%s' % key)(**kwargs[key])
        eval('self.%s' % key)()
        #self.kline_draw(**kwargs[key])
        """

    def graph_attr(self, **kwargs):

        if 'title' in kwargs.keys():
            self.graph_curr.set_title(kwargs['title'])

        if 'legend' in kwargs.keys():
            self.graph_curr.legend(loc=kwargs['legend'], shadow=True)

        if 'xlabel' in kwargs.keys():
            self.graph_curr.set_xlabel(kwargs['xlabel'])

        self.graph_curr.set_ylabel(kwargs['ylabel'])
        self.graph_curr.set_xlim(0, len(self.df_ohlc.index))  # 设置一下x轴的范围
        self.graph_curr.set_xticks(range(0, len(self.df_ohlc.index), kwargs['xticks']))  # X轴刻度设定 每15天标一个日期

        if 'xticklabels' in kwargs.keys():
            self.graph_curr.set_xticklabels(
                [self.df_ohlc.index.strftime(kwargs['xticklabels'])[index] for index in
                 self.graph_curr.get_xticks()])  # 标签设置为日期

            # X-轴每个ticker标签都向右倾斜45度
            for label in self.graph_curr.xaxis.get_ticklabels():
                label.set_rotation(45)
                label.set_fontsize(10)  # 设置标签字体
        else:
            for label in self.graph_curr.xaxis.get_ticklabels():
                label.set_visible(False)
if  __name__ == '__main__':

    if True:
        layout_dict = {'figsize': (14, 8),
                       'nrows': 3,
                       'ncols': 1,
                       'left': 0.08,
                       'bottom': 0.15,
                       'right': 0.95,
                       'top': 0.95,
                       'wspace': None,
                       'hspace': 0,
                       'height_ratios': [1.5, 1, 1],
                       'subplots': ['kgraph', 'cashgraph', 'cmppfgraph']}

        subplots_dict = {'graph_fst': {'graph_name': 'kgraph',
                                       'graph_type': {'trade': None,
                                                      'close_retrace': None
                                                      },
                                       'title': u"000651 格力电器-回测分析",
                                       'ylabel': u"价格",
                                       'xticks': 15,
                                       'legend': 'best'
                                       },
                         'graph_sec': {'graph_name': 'cashgraph',
                                       'graph_type': {'cash_profit': 100000  # 初始资金
                                                      },
                                       'ylabel': u"资金收益和回撤",
                                       'xticks': 15,
                                       'legend': 'best',
                                       },
                         'graph_fth': {'graph_name': 'cmppfgraph',
                                       'graph_type': {'cmp_profit': None
                                                      },
                                       'ylabel': u"策略收益VS基准收益",
                                       'xlabel': u"日期",
                                       'xticks': 15,
                                       'legend': 'best',
                                       'xticklabels': '%Y-%m-%d'
                                       },
                         }
        draw_stock = MultiTraceIf(**layout_dict)
        draw_stock.graph_run(df, **subplots_dict)#只需给一个df即可
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值