金融量化-基于K线形态锤子线的趋势跟踪策略

本文深入探讨了基于K线形态的金融量化策略,重点介绍锤子线在趋势跟踪中的应用。策略原理是下跌趋势中,锤子线的出现可能预示反转,以下跌趋势中锤子线作为开仓信号,并采用移动止损方式设置止损。内容包括锤子线定义、策略实现细节、止损条件及形态要点,并提出了策略改进和优化的思考,如结合成交量、其他形态和技术指标来增强交易信号的可靠性。

1.基本原理

1.1 K线部位定义:

实体:某一根K线开盘价和收盘价之间部分;
上影线:某一根K线最高价到实体上端的部分;
下影线:某一根K线最低价到实体下端的部分;

1.2 锤子线定义

实体处于整个价格区间上端,实体颜色本身不影响;
下影线长度至少达到实体高度的2倍;
上影线很短;

1.3 策略原理

下跌过程中,当某一日出现锤子线,意味着当天行情先继续下跌后出现大幅反弹,行情可能由此反转;
由此以观察期均线识别趋势下跌,以下跌趋势中出现锤子线作为开仓信号; 采用移动止损方式进行止损构建此策略;

1.4 止损条件

当天最低价 < max(均价-观察期内一定倍数的标准差,开仓价-开仓时标准差);

1.5 形态要点:

在出现锤头线(锤子线)之前,股价需经过一段时间的下跌后,处于下跌趋势中,此时出现此形态才具有参考意义;
锤头实体越小,下影线越长,止跌作用就越明显,参考价值越大;

2.策略实现

2.1 收集并计算所需数据

import pandas as pd
import numpy as np
import tushare as ts
code = '002398'         # 股票代码
body_size = 0.03        # 表示锤子实体大小上限,基准为当日开盘价,实体不能太大,波动范围限制在3%;
head_size = 0.5         # 表示锤子上影线长度上限,基准为下影线长度,上影线要短一点,不能超过下影线的的一半;
tail_size = 2           # 表示下影线与实体大小比值,下影线要大于实体两倍;
length = 10             # 表示观察期时间长短;
stoplose_trigger = 1    # 表示当价格偏离均线满足几倍标准差时止损
data.sort_index(ascending=True, inplace=True)
data.head()
open high close low volume amount
date
2012-01-04 6.64 6.80 6.40 6.39 283430.0 4564127.0
2012-01-05 6.38 6.40 5.76 5.76 820954.0 12005136.0
2012-01-06 5.71 5.83 5.70 5.43 972637.0 13330505.0
2012-01-09 5.69 5.97 5.94 5.57 536522.0 7710121.0
2012-01-10 5.94 6.27 6.21 5.94 1121594.0 17023694.0
data.reset_index(inplace=True)        #把索引设置成为默认;为了后面交易策略逻辑循环更方便一些;
data.head()
date open high close low volume amount
0 2012-01-04 6.64 6.80 6.40 6.39 283430.0 4564127.0
1 2012-01-05 6.38 6.40 5.76 5.76 820954.0 12005136.0
2 2012-01-06 5.71 5.83 5.70 5.43 972637.0 13330505.0
3 2012-01-09 5.69 5.97 5.94 5.57 536522.0 7710121.0
4 2012-01-10 5.94 6.27 6.21 5.94 1121594.0 17023694.0
data['pct_change'] = data['close'].pct_change()
data['ma'] = data['close'].rolling(length).mean()
data['std'] = data['close'].rolling(length).std()
del data['volume']
del data['amount']
data
//+------------------------------------------------------------------+ //| MACD_Quantitative_EA.mq4 | //| Copyright 2025, Expert Advisor Developer | //| https://yourwebsite.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Your Name" #property link "https://yourwebsite.com/" #property version "1.00" #property strict // 输入参数 input int FastEMA = 12; // 快速EMA周期 input int SlowEMA = 26; // 慢速EMA周期 input int SignalSMA = 9; // 信号线周期 input double LotSize = 0.1; // 固定交易手数 input int StopLoss = 100; // 止损点数 input int TakeProfit = 200; // 止盈点数 input int TrailingStart = 50; // 启动跟踪止损的盈利点数 input int TrailingStop = 30; // 跟踪止损点数 input bool UseTrailingStop = true; // 是否启用跟踪止损 input bool UseMACDAreaSignal = true; // 是否启用MACD面积缩小信号 input bool UseMACDAreaClose = true; // 是否启用MACD面积扩大平仓 input double MinMACDArea = 0.0001; // MACD最小有效面积 input int AreaLookback = 5; // 面积回溯周期 input int MaxTrendBars = 8; // 趋势末端最大连续上涨/下跌根数 input int DivergenceLookback = 20; // 背离检测周期 input int CrossAngleLookback = 3; // MACD交叉角度检测周期 input double DistanceThreshold = 0.0002; // MACD线与信号线最小距离 input int AccelerationLookback = 5; // 加速度计算周期 // 全局变量 int ticket = 0; //+------------------------------------------------------------------+ //| 初始化函数 | //+------------------------------------------------------------------+ int OnInit() { Print("MACD量化交易EA已加载"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 主函数 OnTick | //+------------------------------------------------------------------+ void OnTick() { if (OrdersTotal() > 0) { if (UseMACDAreaClose) CheckMACDAreaClose(); // 检查MACD面积是否扩大,决定是否平仓 ManageTrailingStop(); // 管理跟踪止损 } if (OrdersTotal() == 0) { int signal = 0; // 1. 基础金叉/死叉 signal = GetMACDSignal(); if (signal == 0 && UseMACDAreaSignal) signal = GetMACDAreaSignal(); // 如果没有金叉/死叉,再判断面积缩小信号 if (signal == 0) signal = GetMACDTrendSignal(); // 最后判断趋势延续信号 if (signal == 0) signal = DetectMACDTopBottom(); // 判断顶部/底部信号 if (signal == 0) signal = DetectMACDCombinedDivergence(); // 加入背离信号 if (signal == 0) signal = IsMACDPeakOrValley(); // 加入柱形态信号 if (signal == 0) signal = IsMACDHistogramCrossZero(); // 新增:柱零轴穿越 if (signal == 0) signal = GetMACDSignalWithZeroZone(); // 新增:判断金叉是否在0轴上方 if (signal == 0) signal = CheckMACDHistogramReacceleration(); // 新增:二次放大信号 if (signal == 0) signal = DetectMACDTrendAcceleration(); // 新增:线斜率变化 if (signal == 1) OpenBuyOrder(); // 做多 else if (signal == -1) OpenSellOrder(); // 做空 } } //+------------------------------------------------------------------+ //| 获取MACD金叉/死叉信号 | //+------------------------------------------------------------------+ int GetMACDSignal() { double macdMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 0); double macdSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, 0); double macdPrevMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 1); double macdPrevSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, 1); // 金叉:当前MACD线上穿信号线 if (macdPrevMain < macdPrevSignal && macdMain > macdSignal) { if (IsMACDCrossWithSteepAngle() && GetMACDLineDistanceFromSignal() > DistanceThreshold) return 1; } // 死叉:当前MACD线下穿信号线 if (macdPrevMain > macdPrevSignal && macdMain < macdSignal) { if (IsMACDCrossWithSteepAngle() && GetMACDLineDistanceFromSignal() > DistanceThreshold) return -1; } return 0; } //+------------------------------------------------------------------+ //| 获取MACD面积缩小信号(优化版:连续5根K线) | //+------------------------------------------------------------------+ int GetMACDAreaSignal() { double hist[5] = {0, 0, 0, 0, 0}; // 显式初始化 for (int i = 0; i < 5; i++) { hist[i] = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); } // 做多信号:负柱状图连续缩小(下跌动能减弱) bool shrinkingNegative = true; for (int i = 0; i < 4; i++) { if (MathAbs(hist[i]) >= MathAbs(hist[i + 1])) { shrinkingNegative = false; break; } } if (shrinkingNegative && hist[0] < 0 && hist[1] < 0 && hist[2] < 0 && hist[3] < 0 && hist[4] < 0) return 1; // 做空信号:正柱状图连续缩小(上涨动能减弱) bool shrinkingPositive = true; for (int i = 0; i < 4; i++) { if (hist[i] <= hist[i + 1]) { shrinkingPositive = false; break; } } if (shrinkingPositive && hist[0] > 0 && hist[1] > 0 && hist[2] > 0 && hist[3] > 0 && hist[4] > 0) return -1; return 0; // 无信号 } //+------------------------------------------------------------------+ //| 获取MACD趋势信号(在0轴上方未跌破则继续做多,反之做空) | //+------------------------------------------------------------------+ int GetMACDTrendSignal() { double hist[5] = {0, 0, 0, 0, 0}; // 显式初始化 for (int i = 0; i < 5; i++) { hist[i] = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); } // 多头趋势:所有MACD柱都在0轴上方,且未跌破 bool allAboveZero = true; for (int i = 0; i < 5; i++) { if (hist[i] <= 0) { allAboveZero = false; break; } } if (allAboveZero) return 1; // 空头趋势:所有MACD柱都在0轴下方,且未上穿 bool allBelowZero = true; for (int i = 0; i < 5; i++) { if (hist[i] >= 0) { allBelowZero = false; break; } } if (allBelowZero) return -1; return 0; // 无趋势信号 } //+------------------------------------------------------------------+ //| 判断MACD是否出现顶部/底部形态(连续上涨/下跌后反转) | //+------------------------------------------------------------------+ int DetectMACDTopBottom() { int trendBars = CountMACDBarTrend(); double currentHist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, 0); double prevHist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, 1); // 顶部:连续上涨超过阈值,且当前柱反转 if (currentHist > 0 && prevHist > 0 && currentHist < prevHist && trendBars >= MaxTrendBars) return -1; // 底部:连续下跌超过阈值,且当前柱反转 if (currentHist < 0 && prevHist < 0 && currentHist > prevHist && trendBars >= MaxTrendBars) return 1; return 0; } //+------------------------------------------------------------------+ //| 检测MACD面积与价格背离 | //+------------------------------------------------------------------+ int DetectMACDAreaDivergence() { double priceHigh = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, DivergenceLookback, 0)); double priceLow = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, DivergenceLookback, 0)); double areaHigh = CalculateMACDArea(DivergenceLookback); double areaLow = CalculateMACDArea(DivergenceLookback); // 顶部背离:价格创新高,但MACD面积未创新高 if (Bid > priceHigh && areaHigh < CalculateMACDArea(DivergenceLookback - 5)) return -1; // 底部背离:价格创新低,但MACD面积未创新低 if (Ask < priceLow && areaLow > CalculateMACDArea(DivergenceLookback - 5)) return 1; return 0; } //+------------------------------------------------------------------+ //| 检测MACD柱连续上涨/下跌与价格背离 | //+------------------------------------------------------------------+ int DetectMACDBarDivergence() { double priceHigh = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, DivergenceLookback, 0)); double priceLow = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, DivergenceLookback, 0)); int trendBars = CountMACDBarTrend(); // 顶部背离:价格创新高,但MACD连续上涨根数未创新高 if (Bid > priceHigh && trendBars < DivergenceLookback - 3) return -1; // 底部背离:价格创新低,但MACD连续下跌根数未创新低 if (Ask < priceLow && trendBars < DivergenceLookback - 3) return 1; return 0; } //+------------------------------------------------------------------+ //| 检测MACD面积和根数双重背离(最强信号) | //+------------------------------------------------------------------+ int DetectMACDCombinedDivergence() { int areaSignal = DetectMACDAreaDivergence(); int barSignal = DetectMACDBarDivergence(); if (areaSignal == -1 && barSignal == -1) return -1; // 双重顶部背离 if (areaSignal == 1 && barSignal == 1) return 1; // 双重底部背离 return 0; } //+------------------------------------------------------------------+ //| 检测MACD柱是否出现“山峰”或“谷底”形态(动能衰竭) | //+------------------------------------------------------------------+ int IsMACDPeakOrValley(int lookback = 5) { double hist[5] = {0, 0, 0, 0, 0}; // 显式初始化 for (int i = 0; i < 5; i++) hist[i] = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); // 山峰形态(中间最高) if (hist[1] < hist[2] && hist[2] > hist[3] && hist[0] < hist[2]) return 1; // 谷底形态(中间最低) if (hist[1] > hist[2] && hist[2] < hist[3] && hist[0] > hist[2]) return -1; return 0; } //+------------------------------------------------------------------+ //| 判断MACD线与信号线交叉是否角度陡峭 | //+------------------------------------------------------------------+ bool IsMACDCrossWithSteepAngle(int lookback = 3) { double angle = 0; for (int i = 0; i < lookback - 1; i++) { double currentMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, i); double currentSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, i); double nextMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, i + 1); double nextSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, i + 1); angle += MathAbs(currentMain - currentSignal) - MathAbs(nextMain - nextSignal); } return MathAbs(angle) > 0.0001; } //+------------------------------------------------------------------+ //| 计算MACD线与信号线之间的平均距离(用于衡量趋势强度) | //+------------------------------------------------------------------+ double GetMACDLineDistanceFromSignal(int lookback = 5) { double sum = 0; for (int i = 0; i < lookback; i++) { double macd = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, i); double signal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, i); sum += MathAbs(macd - signal); } return sum / lookback; } //+------------------------------------------------------------------+ //| 判断MACD线是否刚刚穿越 0 轴(趋势强度信号) | //+------------------------------------------------------------------+ int IsMACDLineCrossZero() { double macdMain0 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 0); double macdMain1 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 1); if (macdMain1 < 0 && macdMain0 > 0) return 1; // 从下向上穿越 if (macdMain1 > 0 && macdMain0 < 0) return -1; // 从上向下穿越 return 0; } //+------------------------------------------------------------------+ //| 判断MACD柱是否刚刚穿越零轴(趋势延续信号) | //+------------------------------------------------------------------+ int IsMACDHistogramCrossZero() { double hist0 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, 0); double hist1 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, 1); if (hist1 < 0 && hist0 > 0) return 1; // 从下向上穿越 if (hist1 > 0 && hist0 < 0) return -1; // 从上向下穿越 return 0; } //+------------------------------------------------------------------+ //| 判断金叉是否发生在0轴上方/下方(增强信号强度) | //+------------------------------------------------------------------+ int GetMACDSignalWithZeroZone() { double macdMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 0); double macdSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, 0); double macdPrevMain = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, 1); double macdPrevSignal = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 1, 1); if (macdPrevMain < macdPrevSignal && macdMain > macdSignal) { if (macdMain > 0) return 1; // 在0轴上方金叉,强度更高 else return 0; // 在0轴下方金叉,不采用 } if (macdPrevMain > macdPrevSignal && macdMain < macdSignal) { if (macdMain < 0) return -1; // 在0轴下方死叉,强度更高 else return 0; // 在0轴上方死叉,不采用 } return 0; } //+------------------------------------------------------------------+ //| 检测MACD线斜率变化(判断趋势是否加速/减速) | //+------------------------------------------------------------------+ int DetectMACDTrendAcceleration() { double slope = 0; for (int i = 0; i < 3; i++) { double current = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, i); double next = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 0, i + 1); slope += (next - current); } if (slope > 0) return 1; // 加速上涨 if (slope < 0) return -1; // 加速下跌 return 0; } //+------------------------------------------------------------------+ //| 检测MACD柱的“二次放大”信号 | //+------------------------------------------------------------------+ int CheckMACDHistogramReacceleration() { double hist[5] = {0, 0, 0, 0, 0}; for (int i = 0; i < 5; i++) hist[i] = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); // 判断是否先缩小后放大(二次加速) if (hist[0] < hist[1] && hist[1] > hist[2] && hist[2] < hist[3] && hist[3] < hist[4]) return 1; // 多头二次加速 if (hist[0] > hist[1] && hist[1] < hist[2] && hist[2] > hist[3] && hist[3] > hist[4]) return -1; // 空头二次加速 return 0; } //+------------------------------------------------------------------+ //| 检查MACD面积是否缩小(用于平仓) | //+------------------------------------------------------------------+ void CheckMACDAreaClose() { for (int i = 0; i < OrdersTotal(); i++) { if (!OrderSelect(i, SELECT_BY_POS)) continue; if (OrderSymbol() != Symbol()) continue; double currentArea = CalculateMACDArea(AreaLookback); if (currentArea == 0) continue; int type = OrderType(); if (type == OP_BUY) { // 多单:MACD面积缩小 + 持续下降趋势 if (MathAbs(currentArea) < MinMACDArea || IsMACDAreaShrinking(AreaLookback)) { if (!OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrRed)) Print("平仓失败,错误码: ", GetLastError()); else Print("【MACD面积衰减】多单平仓 @ ", DoubleToStr(Bid, Digits)); } } if (type == OP_SELL) { // 空单:MACD面积缩小 + 持续下降趋势 if (MathAbs(currentArea) < MinMACDArea || IsMACDAreaShrinking(AreaLookback)) { if (!OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrRed)) Print("平仓失败,错误码: ", GetLastError()); else Print("【MACD面积衰减】空单平仓 @ ", DoubleToStr(Ask, Digits)); } } } } //+------------------------------------------------------------------+ //| 开多单 | //+------------------------------------------------------------------+ void OpenBuyOrder() { double sl = Ask - StopLoss * Point; double tp = Ask + TakeProfit * Point; ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "MACD Buy", 0, 0, clrGreen); if (ticket < 0) Print("多单开仓失败,错误码: ", GetLastError()); else Print("【多单开仓】价格: ", DoubleToStr(Ask, Digits), " 止损: ", DoubleToStr(sl, Digits), " 止盈: ", DoubleToStr(tp, Digits)); } //+------------------------------------------------------------------+ //| 开空单 | //+------------------------------------------------------------------+ void OpenSellOrder() { double sl = Bid + StopLoss * Point; double tp = Bid - TakeProfit * Point; ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp, "MACD Sell", 0, 0, clrRed); if (ticket < 0) Print("空单开仓失败,错误码: ", GetLastError()); else Print("【空单开仓】价格: ", DoubleToStr(Bid, Digits), " 止损: ", DoubleToStr(sl, Digits), " 止盈: ", DoubleToStr(tp, Digits)); } //+------------------------------------------------------------------+ //| 管理跟踪止损 | //+------------------------------------------------------------------+ void ManageTrailingStop() { for (int i = 0; i < OrdersTotal(); i++) { if (!OrderSelect(i, SELECT_BY_POS)) continue; if (OrderSymbol() != Symbol()) continue; double openPrice = OrderOpenPrice(); double currentPrice = (OrderType() == OP_BUY) ? Bid : Ask; double profitPoints = (OrderType() == OP_BUY) ? (currentPrice - openPrice) / Point : (openPrice - currentPrice) / Point; if (UseTrailingStop && profitPoints >= TrailingStart) { double newStopLoss = 0; if (OrderType() == OP_BUY) newStopLoss = currentPrice - TrailingStop * Point; else newStopLoss = currentPrice + TrailingStop * Point; if (newStopLoss != OrderStopLoss()) { if (!OrderModify(OrderTicket(), openPrice, newStopLoss, OrderTakeProfit(), 0, clrGreen)) Print("跟踪止损更新失败,错误码: ", GetLastError()); else Print("【跟踪止损更新】新止损: ", DoubleToStr(newStopLoss, Digits)); } } } } //+------------------------------------------------------------------+ //| 计算MACD面积(Histogram的累计值) | //+------------------------------------------------------------------+ double CalculateMACDArea(int bars = 5) { double area = 0; for (int i = 0; i < bars; i++) { double hist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); area += hist; } return area; } //+------------------------------------------------------------------+ //| 判断MACD面积是否连续缩小(用于趋势衰减判断) | //+------------------------------------------------------------------+ bool IsMACDAreaShrinking(int bars = 5) { double areas[]; ArrayResize(areas, bars); for (int i = 0; i < bars; i++) { areas[i] = 0; for (int j = 0; j <= i; j++) { double hist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, j); areas[i] += hist; } } // 多头:面积持续缩小(正值减少) if (areas[0] > 0) { for (int i = 0; i < bars - 1; i++) if (MathAbs(areas[i]) <= MathAbs(areas[i + 1])) return false; return true; } // 空头:面积持续缩小(负值减少) else if (areas[0] < 0) { for (int i = 0; i < bars - 1; i++) if (MathAbs(areas[i]) <= MathAbs(areas[i + 1])) return false; return true; } return false; } //+------------------------------------------------------------------+ //| 判断MACD柱状图连续上涨/下跌的根数 | //+------------------------------------------------------------------+ int CountMACDBarTrend(int maxBars = 20) { int count = 0; double prevHist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, 0); for (int i = 1; i < maxBars; i++) { double currentHist = iMACD(NULL, 0, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE, 2, i); if ((prevHist > 0 && currentHist > prevHist) || (prevHist < 0 && currentHist < prevHist)) { count++; prevHist = currentHist; } else break; } return count; } 帮我加K线形态
最新发布
07-24
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值