外汇货币对的交易成本(The trade cost of Forex Currency) Part2

12 四月 2018, 05:36
Yupeng Xiao
2
483

内容目录

  • 概述
  • 点的概念
  • 点值
  • 点差成本
  • 输出全部外汇货币对的点差成本
  • 测试
  • 结论


点差成本

价格和点差

图1. 部分外汇货币对的买卖价及点差值


点差是买入价(Ask)与卖盘价(Bid)之间差额的点数。图1中最右边一列即为各个货币对的点差值。由于点差的存在,因此买卖任何货币对都会有一个初始的损失,该损失即为该货币对的交易成本。

1.  公式

根据上文中公式(1)、(2)、(3)、(4)可将交易成本概括为以下三种情况:

1) 利润货币的直盘货币对基础货币为账户货币

以美元账户为示例,例如:USDJPY,EURJPY,利润货币都为JPY,JPY的直盘货币对为USDJPY,USDJPY的基础货币为账户货币USD,

这种情况下点差产生的交易成本是:成本公式1         (公式5)

其中:

  • Lots:交易手数
  • ContractSize:一标准手合约大小,外汇品种为100,000基础货币
  • SymbPoint:该货币对波动最小点
  • Spread:该货币对点差
  • Price:利润货币的直盘货币对的当前价格。

2) 利润货币为账户货币

以美元账户为示例,例如:EURUSD,GBPUSD等

这种情况下点差产生的交易成本是:成本公式2         (公式6)

3) 利润货币的直盘货币对基础货币非账户货币

以美元账户为示例,例如:EURGBP,GBPAUD等

这种情况下点差产生的交易成本是:成本公式3         (公式7)

其中:Price为利润货币的直盘货币对当前价格。

2.  代码

首先定义CSpreadCost类,CSpreadCost类用于计算货币对的交易成本等相关操作。计算点差成本的代码如下所示,其中CSpreadCost::GetSpread() 用于获取货币对的点差值,CSpreadCost::GetSpreadCost() 用于计算点差产生的交易成本。黄色背景部分为公式(6)对应的交易成本计算代码,绿色背景部分为公式(5)、(7)对应的交易成本计算代码。

//+------------------------------------------------------------------+
//| Get spread                                                       |
//+------------------------------------------------------------------+
int CSpreadCost::GetSpread(string Symb)
{
   int spread;
   spread = (int)::SymbolInfoInteger(Symb,SYMBOL_SPREAD);
   return(spread);
}
//+------------------------------------------------------------------+
//| Get spread cost                                                  |
//+------------------------------------------------------------------+
double CSpreadCost::GetSpreadCost(string Symb)
{
   double price;
   double ContractSize = ::SymbolInfoDouble(Symb,SYMBOL_TRADE_CONTRACT_SIZE);
   double SymbPoint = ::SymbolInfoDouble(Symb,SYMBOL_POINT);
   string SymbProfit = ::SymbolInfoString(Symb,SYMBOL_CURRENCY_PROFIT);
   int spread = GetSpread(Symb);
   double spreadcost = 0;
   if(SymbProfit == AccountSymbol)
   {
      spreadcost = Lots*ContractSize*SymbPoint*spread;
   }
   else
   {
      price = oSymbs.FxSymbPrice(SymbProfit);
      spreadcost = Lots*ContractSize*SymbPoint*spread*price;
   }
   
   return(spreadcost);
}

在公式(5)、(7)中Price均为利润货币的直盘货币对当前价格,公式(5)可以转化为成本公式4

因此在CSpreadCost::GetSpread() 中,将公式(5)、(7)对应的交易成本计算方法统一成为一个公式。

由于平台中可能会没有利润货币的直盘货币对的报价,例如在英镑账户中,USDHKD的利润货币为港币HKD,因为账户货币为GBP,所以其直盘货币对应为GBPHKD,而平台中可能没有GBPHKD的直接报价,对此作出如下处理:

  • 利润货币与美元的报价中,美元为基础货币;账户货币与美元的报价中,美元为基础货币。此时有:组合价格1

  • 利润货币与美元的报价中,美元为基础货币;账户货币与美元的报价中,账户货币为基础货币。此时有:组合价格2

  • 利润货币与美元的报价中,利润货币为基础货币;账户货币与美元的报价中,美元为基础货币。此时有:组合价格3

  • 利润货币与美元的报价中,利润货币为基础货币;账户货币与美元的报价中,账户货币为基础货币。此时有:组合价格4

其中:ProfitCur.为利润货币,AccountCur.为账户货币。

Price的计算代码在CForexSymbols类中实现,CForexSymbols类用于获取货币对的相关操作,其中CForexSymbols::FxSymbPrice() 用于计算以指定货币为基础货币的直盘货币对价格,具体代码如下:

//+------------------------------------------------------------------+
//| Get the Symbol price,                                            |
//| which base currency is SymbBase,                                 |
//| and the profit currency is AccountSymbol                         | 
//+------------------------------------------------------------------+
double CForexSymbols::FxSymbPrice(string SymbBase)
{
   MqlTick LatestPrice;
   string SymbProfitFullName;
   string SymbFullName1;
   string SymbFullName2;
   double price = -1;
   
   if(SymbBase == AccountSymbol)
   {
      ::Print(__FUNCTION__," > Parameters error!!");
      return(-1);
   }
   
   SymbProfitFullName = FxSymbFullName(SymbBase);
   
   if(SymbProfitFullName == "")//no currency contains SymbBase and AccountSymbol in the platform
   {
      SymbFullName1 = FxSymbFullName(SymbBase,"USD");
      SymbFullName2 = FxSymbFullName(AccountSymbol,"USD");
      if(FxSymbolType(SymbFullName1,"USD") == 0)
      {
         ::SymbolInfoTick(SymbFullName1,LatestPrice);
         price = 1/LatestPrice.bid;
         if(FxSymbolType(SymbFullName2,"USD") == 0)
         {
            ::SymbolInfoTick(SymbFullName2,LatestPrice);
            price = price*LatestPrice.bid;
         }
         else if(FxSymbolType(SymbFullName2,"USD") == 1)
         {
            ::SymbolInfoTick(SymbFullName2,LatestPrice);
            price = price/LatestPrice.bid;
         }
      }
      else if(FxSymbolType(SymbFullName1,"USD") == 1)
      {
         ::SymbolInfoTick(SymbFullName1,LatestPrice);
         price = LatestPrice.bid;
         if(FxSymbolType(SymbFullName2,"USD") == 0)
         {
            ::SymbolInfoTick(SymbFullName2,LatestPrice);
            price = price*LatestPrice.bid;
         }
         else if(FxSymbolType(SymbFullName2,"USD") == 1)
         {
            ::SymbolInfoTick(SymbFullName2,LatestPrice);
            price = price/LatestPrice.bid;
         }  
      }
   }
   else
   {
      if(FxSymbolType(SymbProfitFullName) == 0)//AccountSymbol is base currency
      {
         ::SymbolInfoTick(SymbProfitFullName,LatestPrice);
         price = 1/LatestPrice.bid;
      }
      else if(FxSymbolType(SymbProfitFullName) == 1)//SymbBase is base currency
      {
         ::SymbolInfoTick(SymbProfitFullName,LatestPrice);
         price = LatestPrice.bid;
      }
   }
   return(price);
}

绿色背景部分为平台中不存在利润货币的直盘货币对报价时,计算其价格的代码实现。上述代码中FxSymbFullName()用于:1.返回指定货币的直盘货币对;2.返回两个货币组成的货币对;3.货币对中基础货币或利润货币的直盘货币对。FxSymbolType()用于判断指定货币对或是两个货币组成的货币对的类型,具体代码如下所示:

//+------------------------------------------------------------------+
//| get the symbol type when account currency is USD                 |
//| 0: like USDJPY,USDCAD  1: like EURUSD,GBPUSD                     |
//| 2-cross symbols: like EURAUD,CADJPY                              |
//| when account currency is EUR                                     |
//| 0: like EURUSD,EURJPY  1: don't exist                            |
//| 2-cross: like GBPUSD,USDJPY                                      |
//| Other account currency is similar                                |
//+------------------------------------------------------------------+  
int CForexSymbols::FxSymbolType(string FxSymb)
{
   if(::StringSubstr(FxSymb,0,3)==AccountSymbol) return(0);
   else if(::StringSubstr(FxSymb,3,3)==AccountSymbol) return(1);
   else return(2);
}
//+------------------------------------------------------------------+
//| get the postion of HalfSymb in the FxSymb                        |
//+------------------------------------------------------------------+  
int CForexSymbols::FxSymbolType(string FxSymb,string HalfSymb)
{
   if(::StringSubstr(FxSymb,0,3)==HalfSymb) return(0);
   else if(::StringSubstr(FxSymb,3,3)==HalfSymb) return(1);
   else return(-1);
}
//+------------------------------------------------------------------+
//| Judge whether this symbol is exist                               |
//+------------------------------------------------------------------+  
bool CForexSymbols::IsSymbolExist(string symb)
{
   double rvalue;//receiving the value of the requested property.
   if(::SymbolInfoDouble(symb,SYMBOL_BID,rvalue))//Symbol Exist
   {
      return(true);
   }
   else
   {
      if(::GetLastError() == ERR_MARKET_UNKNOWN_SYMBOL)
      {
         return(false);
      }
      return(true);
   }
}

CForexSymbols::IsSymbolExist()用于判断平台里是否有指定货币对的报价。