根据移动平均线信号交易的EA FlyerV200.mq4-MT4 EA-峰汇在线
诚信为本
量力而为
当前位置:峰汇在线 > MetaTrader 4 > MT4 EA > 正文

根据移动平均线信号交易的EA FlyerV200.mq4

FlyerV200 EA根据均线的信号在自动交易。

源码:

//+------------------------------------------------------------------+
//|                                                    FlyerV200.mq4 |
//|                                          (GirlFlyer)  Marci Dunn |
//+------------------------------------------------------------------+
#property copyright "Marci Dunn"
#property link      "http://www.125808047.com"

extern double  LotPercentage =5; 
extern double  MinVal=5000;
extern int     StopLossVal = 60; 
extern int     TimePeriod = 30;                                       
extern int     UseTS;                                     
extern int     TrailingStopLevel = 75;                                   
extern double  BrokerMinLotSize = 0.1;                                           
extern int     FixedLots = 0;                                        
extern double  MyLotSize = 1;
extern int     LotValue = 0; 
extern int     MarginVal = 100; 
extern int    LimitHours = 1; 
extern int    StartHours = 21;
extern int    StartMins = 0;
extern int    EndHours = 7;
extern int    EndMins = 0;                                        
                                        
int       OpenOrderB; 
int       OpenOrderS;
int       OrderFlagB = 0;
int       OrderFlagS = 0;
datetime  TimeofCross;
int       CrossFlag = 0; 
double    PointAdjust = 0;
int       WaitTime = 150; 

int       MA = 0;
int       MA1 = 0;
int       MA2 = 0;
int       MA3,MA4,MA5;                 
int       MaxBars = 0;
int       GapSize = 0; 
                                             
double    ILotVal;
int       InvalidFB,InvalidFS;
int       JustOrderedB, JustOrderedS;
int       SignalFB,SignalFS;
double    HPriceB,LPriceS,OPriceB,OPriceS;
double    PointSpreadB;
double    PointSpreadS;
int       QuickSpread;
int       TrendCnt;
double    ProfitPercent;
                                  
datetime  AlertTimer;

string    SymbolList[15] = {"EURUSD","GBPUSD","USDCHF","USDJPY","EURJPY","AUDUSD"};
double    PointArray[15] = {-0.0001,-0.0001,-0.0001,-0.01,-0.01,0.0001}; 

int       TrendArray[15] = {22,22,48,35,15,48,0,0,0};  
int       MAArray[15] = {4,4,4,8,4,3,8,8};  
int       MA1Array[15] = {6,8,16,14,5,18,8,8};
int       MA2Array[15] = {8,10,18,16,7,20,10,10}; 
int       MA3Array[15] = {10,10,10,14,10,10,10,10};  
int       MA4Array[15] = {24,18,40,36,20,80,18,18};
                                                    
int       MA5Array[15] = {36,28,50,48,30,90,28,28};
int       MaxBarArray[15] = {4,5,6,8,3,6,4,4};
int       GapArray[15] = {18,20,20,16,15,20,20,20};
int       ProfitArray[15] = {25,75,45,50,25,65,75,75}; 
int       SpreadArray[15] = {50,40,100,40,1000,100,35,35};
                                             
string    VerString = "V200";                                             
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{ 
  int  x; 
   
  AlertTimer = CurTime();
  if(LotValue==0)
    {
      ILotVal = 100000 / MarginVal;
    }
  else
    if(LotValue==1)
      {
        ILotVal = 10000 / MarginVal;
      }
      
  for(x=0;x<15;x++)
    {
      if(StringFind(Symbol(),SymbolList[x],0)>=0)
        {
          PointAdjust = PointArray[x];
          TrendCnt = TrendArray[x];
          MA = MAArray[x];
          MA1 = MA1Array[x];
          MA2 = MA2Array[x];
          MA3 = MA3Array[x];
          MA4 = MA4Array[x];
          MA5 = MA5Array[x];
          MaxBars = MaxBarArray[x];
          GapSize = GapArray[x];
          ProfitPercent = ProfitArray[x] / 100.0;
          QuickSpread = SpreadArray[x];
        }
    }
   Comment("www.125808047.com");
   return(INIT_SUCCEEDED);
  }

int  CloseCount(int  Ctr)
{
  double  Diffs;
  int  x,Count;
  for(x=0,Count = 0;x<Ctr;x++)
    {
      Diffs += iClose(NULL,TimePeriod,x) - iOpen(NULL,TimePeriod,x);
    }
  Count = Diffs / Point;
  return(Count);
}

int  CloseCountMin(int  Ctr)
{
  int  x,Count;
  for(x=0,Count = 0;x<Ctr;x++)
    {
      if(iClose(NULL,1,x) >= iClose(NULL,1,x+1))
        Count++;
      else
        Count--;
    }
  return(Count);
}

void  CheckToOpenBuy(double  LotSize2)
  {
    int  x,flag,TicketNum;
    double  EMA18[10];
    double  EMA28[10];
    double  WMA5[10];  
    double  WMA8[10];
    datetime  TimeNow;
    int     Trend;
  
    if(OrderFlagB>0)
      return;
    PointSpreadB = iClose(NULL,1,0)-iLow(NULL,1,15);  
    for(x=0;x<MaxBars+1;x++)
      { 
        EMA18[x]=iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
        EMA28[x]=iMA(NULL,TimePeriod,MA5,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
        WMA5[x]=iMA(NULL,TimePeriod,MA1,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
        WMA8[x]=iMA(NULL,TimePeriod,MA2,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
      }
    flag = 0;
    if(WMA5[MaxBars]>EMA18[MaxBars]+PointAdjust && WMA5[MaxBars]>EMA28[MaxBars]+PointAdjust && WMA8[MaxBars]>EMA18[MaxBars]+PointAdjust && WMA8[MaxBars]>EMA28[MaxBars]+PointAdjust)
      {
        for(x=0;x<MaxBars;x++)
              {
                if(WMA5[x]<=EMA18[x] && WMA5[x]<=EMA28[x] && WMA8[x]<=EMA18[x] && WMA8[x]<=EMA28[x])
                  flag=1;
              }
      } 
    if(PointSpreadB > QuickSpread*Point && CloseCountMin(4)>=0)
      flag = 2;
        Trend = CloseCount(TrendCnt);
        if((flag==1 && Trend>0 && CloseCountMin(5)>=0) || flag == 2 ) 
          {
            if(CrossFlag==0)
              {
                TimeofCross = CurTime();
                CrossFlag = 1;
              }
            else
              {
                TimeNow = CurTime();
                if(TimeNow-TimeofCross>WaitTime)
                  {
                    CrossFlag = 0;
                    if(Ask<EMA28[MaxBars]+GapSize*Point)
                      {
                        TicketNum = OrderSend(Symbol(),OP_BUY,LotSize2,Ask,3,Ask-StopLossVal*Point,0,Symbol()+VerString,0,0,Green);
                        if(TicketNum<0)
                          {
                            Print("Error Opening Trade:  Error Code = ",GetLastError(),", Lotsize: ",LotSize2);
                          }
                        else
                          {
                            if(OrderSelect(TicketNum,SELECT_BY_TICKET))
                              {
                                Print("Buy Order Opened at Price:  ",OrderOpenPrice());
                                Print("Trend Count = ",CloseCount(TrendCnt));
                                OpenOrderB = TicketNum;
                                OrderFlagB = 1;
                                InvalidFB = 0;
                                HPriceB = OrderOpenPrice();
                                OPriceB = HPriceB;
                                JustOrderedB = 1;
                              }
                          }
                      }
                  }
              }
          }      
  }
  
void  CheckToOpenSell(double  LotSize2)
{
    int     x,flag,TicketNum;
    double  EMA18[10];
    double  EMA28[10];
    double  WMA5[10];  
    double  WMA8[10];
    datetime  TimeNow;
    int     Trend;
  
    if(OrderFlagS>0)
      return;
    PointSpreadS = iClose(NULL,1,0)-iHigh(NULL,1,15);  
    for(x=0;x<MaxBars+1;x++)
      { 
        EMA18[x]=iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
        EMA28[x]=iMA(NULL,TimePeriod,MA5,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
        WMA5[x]=iMA(NULL,TimePeriod,MA1,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
        WMA8[x]=iMA(NULL,TimePeriod,MA2,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
      }
    flag = 0;
    if(WMA5[MaxBars]<EMA18[MaxBars]-PointAdjust && WMA5[MaxBars]<EMA28[MaxBars]-PointAdjust && WMA8[MaxBars]<EMA18[MaxBars]-PointAdjust && WMA8[MaxBars]<EMA28[MaxBars]-PointAdjust)
      {
        for(x=0;x<MaxBars;x++)
              { 
                if(WMA5[x]>=EMA18[x] && WMA5[x]>=EMA28[x] && WMA8[x]>=EMA18[x] && WMA8[x]>=EMA28[x])
                  flag=1;
              }
      } 
    if(PointSpreadS < -QuickSpread*Point && CloseCountMin(4)<=0)
      flag = 2;
        Trend = CloseCount(TrendCnt);
        if((flag==1 && Trend < 0 && CloseCountMin(5)<=0) || flag ==2 ) 
          {
            if(CrossFlag==0)
              {
                TimeofCross = CurTime();
                CrossFlag = 1;
              }
            else
              {
                TimeNow = CurTime();
                if(TimeNow-TimeofCross>WaitTime) 
                  {
                    CrossFlag = 0;
                    if(Bid>EMA28[MaxBars]-GapSize*Point)
                      {
                        TicketNum = OrderSend(Symbol(),OP_SELL,LotSize2,Bid,3,Bid+StopLossVal*Point,0,Symbol()+VerString,0,0,Green);
                        if(TicketNum<0)
                          {
                            Print("Error Opening Trade:  Error Code = ",GetLastError(),", Lotsize: ",LotSize2);
                          }
                        else
                          {
                            if(OrderSelect(TicketNum,SELECT_BY_TICKET))
                              {
                                Print("Sell Order Opened at Price:  ",OrderOpenPrice());
                                Print("Trend Count = ",CloseCount(TrendCnt));                                
                                OpenOrderS = TicketNum;
                                OrderFlagS = 1;
                                InvalidFS = 0;
                                LPriceS = OrderOpenPrice();
                                OPriceS = LPriceS;
                                JustOrderedS = 1;
                              }
                          }
                      }
                  }
              }
          }
  }

void  CheckToOpen()
  {
    double  LotSize;
    double  R1,R2;
    double  x;
    int     flag;
    int     TimeNowH,TimeNowM;
    
    if(LimitHours>0)
      {
        TimeNowH = Hour();
        TimeNowM = Minute();
        if((TimeNowH == StartHours && TimeNowM >= StartMins) || TimeNowH > StartHours)  
          {
            if(EndHours>=StartHours)
              {
                if((TimeNowH == EndHours && TimeNowM <= EndMins) || TimeNowH < EndHours)
                  {
                    return;
                  }
              }
            else
              return;
          }
        else 
          {
            if(EndHours<= StartHours && ((TimeNowH == EndHours && TimeNowM <= EndMins) || TimeNowH < EndHours))
              return;
          }
      }
    
    if(FixedLots==0)
      {
        LotSize = (LotPercentage/100) * AccountEquity();
        LotSize = LotSize / ILotVal;
        R1 = MathCeil(LotSize); 
        R2 = MathFloor(LotSize);
        for(x=R2,flag=0;x<=R1+BrokerMinLotSize && flag==0;x+=BrokerMinLotSize)
          {
            if(x>LotSize)
              {
                LotSize = x-BrokerMinLotSize;
                flag = 1;
              }
          }
      }
    else
      {
        if(FixedLots==1)
          LotSize = MyLotSize;
      }
    if(LotSize>100)
       LotSize = 100;

    if(!OrderFlagB) 
      {
        if(AccountEquity()>MinVal)
          {
            if(LotSize*ILotVal<AccountFreeMargin())
              {
                 CheckToOpenBuy(LotSize);
              }
            else
              {
                Print("Not Enough Free Margin:  ",LotSize,", ",AccountFreeMargin());
              }
          }
        else
          {
            Print("Equity Value Lower than Minimum Account Value Setting");
          }
      }
          
    if(FixedLots==0)
      {
        LotSize = (LotPercentage/100) * AccountEquity();
        LotSize = LotSize / ILotVal;
        R1 = MathCeil(LotSize); 
        R2 = MathFloor(LotSize);
        for(x=R2,flag=0;x<=R1+BrokerMinLotSize && flag==0;x+=BrokerMinLotSize)
          {
            if(x>LotSize)
              {
                LotSize = x-BrokerMinLotSize;
                flag = 1;
              }
          }
      }
    else
      {
        if(FixedLots==1)
          LotSize = MyLotSize;
      }
    if(LotSize>100)
       LotSize = 100;

    if(!OrderFlagS)
      {
        if(AccountEquity()>MinVal)
          {
            if(LotSize*ILotVal<AccountFreeMargin())
              {
                 CheckToOpenSell(LotSize);
              }
            else
              {
                Print("Not Enough Free Margin:  ",LotSize,", ",AccountFreeMargin());
              }
          }
        else
          {
            Print("Equity Value Lower than Minimum Account Value Setting");
          }
      }
  }
  
void  CheckToCloseBuy()
  {
    int  TicketNum;
    double    SMA8_1,SMA8_2;
    double    LWMA_1,LWMA_2;
    double    EMA18_1,EMA18_2,EMA28_1;
    
    SMA8_1 = iMA(NULL,TimePeriod,MA3,0,MODE_SMA,PRICE_CLOSE,0);
    SMA8_2 = iMA(NULL,TimePeriod,MA3,0,MODE_SMA,PRICE_CLOSE,1);
    LWMA_1 = iMA(NULL,TimePeriod,MA,0,MODE_LWMA,PRICE_CLOSE,0);
    LWMA_2 = iMA(NULL,TimePeriod,MA,0,MODE_LWMA,PRICE_CLOSE,1);
    EMA18_1 = iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,0);
    EMA28_1 = iMA(NULL,TimePeriod,MA5,0,MODE_EMA,PRICE_CLOSE,0);
    EMA18_2 = iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,1);
    
    TicketNum = OpenOrderB;
    bool cg = OrderSelect(TicketNum,SELECT_BY_TICKET);
    if(Bid>HPriceB)
      HPriceB = Bid;
    if(JustOrderedB==1 && LWMA_1 < SMA8_1)
      {
        SignalFB = 1;
      }
    else
      {
        SignalFB = 0;
        JustOrderedB = 0;
      }
    if(LWMA_1< SMA8_1 && SignalFB == 0)  
      {
        if(EMA18_1-EMA28_1<8*Point)   
          {
            if(EMA18_1<EMA18_2-1*Point  || LWMA_1 < EMA28_1)
              {
                if(CloseCountMin(5)<0)
                  {
                    if(Bid>OrderOpenPrice())
                      {
                        CloseBuy(TicketNum);
                        OrderFlagB = 0;
                        InvalidFB = 0;
                      }
                    else
                      {
                        InvalidFB = 1;
                      }
                  }               
              }
            
         }
      }
    if(HPriceB-OPriceB > 28*Point && Bid <= (OPriceB + (ProfitPercent*(HPriceB-OPriceB))) && Bid > OPriceB && (Bid <SMA8_1 || Bid<=OPriceB+5*Point)&& Bid<iClose(NULL,1,1) && SMA8_2 - SMA8_1 > -1.8*Point)
      {
            CloseBuy(TicketNum);
            OrderFlagB = 0;
            InvalidFB = 0;
            return;
      } 
  }
  
void  CheckToCloseSell()
  {
    int  TicketNum;
    double    SMA8_1,SMA8_2;
    double    LWMA_1,LWMA_2;
    double    EMA18_1,EMA18_2,EMA28_1;
    
    SMA8_1 = iMA(NULL,TimePeriod,MA3,0,MODE_SMA,PRICE_CLOSE,0);
    SMA8_2 = iMA(NULL,TimePeriod,MA3,0,MODE_SMA,PRICE_CLOSE,1);
    LWMA_1 = iMA(NULL,TimePeriod,MA,0,MODE_LWMA,PRICE_CLOSE,0);
    LWMA_2 = iMA(NULL,TimePeriod,MA,0,MODE_LWMA,PRICE_CLOSE,1);
    EMA18_1 = iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,0);
    EMA28_1 = iMA(NULL,TimePeriod,MA5,0,MODE_EMA,PRICE_CLOSE,0);
    EMA18_2 = iMA(NULL,TimePeriod,MA4,0,MODE_EMA,PRICE_CLOSE,1);    
    
    TicketNum = OpenOrderS;
    bool cg = OrderSelect(TicketNum,SELECT_BY_TICKET);
    if(Bid<LPriceS)
      LPriceS = Bid;
    if(JustOrderedS==1 && LWMA_1 > SMA8_1)
      {
        SignalFS = 1;
      }
    else
      {
        SignalFS = 0;
        JustOrderedS = 0;
      }
    if(LWMA_1> SMA8_1 && SignalFS == 0)
      {
        if(EMA28_1-EMA18_1<8*Point)
          {      
            if(EMA18_1>EMA18_2+1*Point || LWMA_1 > EMA28_1)
              {
                if(CloseCountMin(5)>0)
                  {
                    if(Ask<OrderOpenPrice())
                      {
                        CloseSell(TicketNum);
                        OrderFlagS = 0;
                      } 
                    else
                      {
                        InvalidFS = 1;
                      }
                   
                  }
              }
          }
      }
    if(OPriceS-LPriceS > 28*Point && Ask >= (OPriceS - (ProfitPercent*(OPriceS-LPriceS))) && Ask < OPriceS && (Ask > SMA8_1 || Ask >= OPriceS-3*Point)&& Ask>iClose(NULL,TimePeriod,1) && SMA8_1-SMA8_2 > -1.8*Point)
      {
        CloseSell(TicketNum);
        OrderFlagS = 0;
        InvalidFS = 0;
        return;
      } 
  }
  
void  CloseBuy(int  Ticket)
  {
    if(OrderSelect(Ticket,SELECT_BY_TICKET))
      {
        if(OrderClose(Ticket,OrderLots(),Bid,3,Red))
          {
            Print("Order#",Ticket," Closed at ",OrderClosePrice());
          }
      }
    else
      {
        Print("Error Closing Ticket#",Ticket);
      }
  }
  
void  CloseSell(int  Ticket)
  {
    if(OrderSelect(Ticket,SELECT_BY_TICKET))
      {
        if(OrderClose(Ticket,OrderLots(),Ask,3,Red))
          {
            Print("Order#",Ticket," Closed at ",OrderClosePrice());
          }
      }
    else
      {
        Print("Error Closing Ticket#",Ticket);
      }
  }

void  CheckForStops()
  {
    datetime  X;
    
    if(OrderFlagB>0)
      {
        if(OrderSelect(OpenOrderB,SELECT_BY_TICKET))
          {
            X = OrderCloseTime();
            if(X>0) 
              {
                OrderFlagB = 0; 
                Print("Order# ",OpenOrderB," StopLoss Close at price:  ",OrderClosePrice());
              }
          }
      }
    if(OrderFlagS>0)
      {
        if(OrderSelect(OpenOrderS,SELECT_BY_TICKET))
          {
            X = OrderCloseTime();
            if(X>0)                
              {
                OrderFlagS = 0;
                Print("Order# ",OpenOrderS," StopLoss Close at price:  ",OrderClosePrice());
              }
          }
      }
  }
  
void  CheckToClose()

  {
    if(OrderFlagB==1)
      {
        CheckToCloseBuy();
      }
    if(OrderFlagS==1)
      {
        CheckToCloseSell();
      }
      
  }
  
void  CheckForModify()
  {
    if(OrderFlagB==0 && OrderFlagS==0)
      return;
    if(OrderFlagB==1)
      {
        if(OrderSelect(OpenOrderB,SELECT_BY_TICKET))
          {
            if(OrderStopLoss()<OrderOpenPrice())
              {
                if(Bid>OrderOpenPrice()+55*Point)
                  {
                    if(OrderModify(OpenOrderB,OrderOpenPrice(),OrderOpenPrice()+15*Point,OrderOpenPrice()+700*Point,0,Yellow)==false)
                      {
                        Print("Error Modifying Order! Code: ",GetLastError());
                      }
                  }
                else
                    
                if(Bid>OrderOpenPrice()+TrailingStopLevel*Point && UseTS == 1)
                  {
                    if(OrderModify(OpenOrderB,OrderOpenPrice(),OrderOpenPrice()+10*Point,OrderOpenPrice()+700*Point,0,Yellow)==false)
                       {
                         Print("Error Modifying Order! Code: ",GetLastError());
                       }
                  }
              }
            else
              {
                if(Bid>(OrderStopLoss()+(TrailingStopLevel*Point*2)) && UseTS == 1)
                  {
                    if(OrderModify(OpenOrderB,OrderOpenPrice(),OrderStopLoss()+(TrailingStopLevel)*Point,OrderStopLoss()+700*Point,0,Yellow)==false)
                      {
                        Print("Error Modifying Order! Code: ",GetLastError());
                      }
                  }
              }
          }
      }
    if(OrderFlagS==1)
      {
        if(OrderSelect(OpenOrderS,SELECT_BY_TICKET))
          {
            if(OrderStopLoss()>OrderOpenPrice())
              {
                if(Ask<OrderOpenPrice()-55*Point)
                  {
                    if(OrderModify(OpenOrderS,OrderOpenPrice(),OrderOpenPrice()-15*Point,OrderOpenPrice()-700*Point,0,Yellow)==false)
                      Print("Error Setting S/L to 5",GetLastError());
                      
                  }
                else
                if(Ask<OrderOpenPrice()-TrailingStopLevel*Point && UseTS == 1)
                  {
                    if(OrderModify(OpenOrderS,OrderOpenPrice(),OrderOpenPrice()-10*Point,OrderOpenPrice()-700*Point,0,Yellow)==false)
                      Print("Error Setting S/L to 5",GetLastError());
                  } 
              
              }
            else
              {
                if(Ask<(OrderStopLoss()-(TrailingStopLevel*Point*2)) && UseTS == 1)
                  {
                    if(OrderModify(OpenOrderS,OrderOpenPrice(),OrderStopLoss()-(TrailingStopLevel)*Point,OrderStopLoss()-700*Point,0,Yellow)==false)
                      {
                        Print("Error Modifying Order! Code: ",GetLastError());
                      }
                  }
              }
          }
      }
  }
  
void CheckForOpenOrders()
  {
    int  x,TotalOrders;
    TotalOrders = OrdersTotal();
    for(x=0;x<TotalOrders;x++)
      {
        if (OrderSelect(x, SELECT_BY_POS, MODE_TRADES))
          {
            if(StringFind(OrderComment(),Symbol()+VerString,0)>=0)
              {
                if(OrderType()==OP_BUY)
                  {
                    OrderFlagB = 1;
                    OpenOrderB = OrderTicket();
                  }
                else
                  if(OrderType()==OP_SELL)
                    {
                      OrderFlagS = 1;
                      OpenOrderS = OrderTicket();
                    }
              }
          }
      }
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
void OnTick()
{
   HideTestIndicators(false);
   CheckForOpenOrders();
   CheckToOpen();
   CheckToClose();
   CheckForModify();
   CheckForStops();
if(CurTime()>=AlertTimer+300)
     {
       AlertTimer += 300;
     } 
   if(OrderFlagB>0 || OrderFlagS>0)
     Comment("Open Orders Exist, Equity = ",AccountEquity());
   else
     Comment("No Open Orders! Waiting for Entry.");
  }
//+------------------------------------------------------------------+
打赏
版权所有转载请注明标题及链接:峰汇在线 » 根据移动平均线信号交易的EA FlyerV200.mq4
上一篇:
下一篇:
分享到: 更多 (0)

如您觉得此文不错请扫码打赏!

支付宝扫一扫打赏

微信扫一扫打赏