内容目录
- 概述
- 点的概念
- 点值
- 点差成本
- 输出全部外汇货币对的点差成本
- 测试
- 结论
点差成本
图1. 部分外汇货币对的买卖价及点差值
点差是买入价(Ask)与卖盘价(Bid)之间差额的点数。图1中最右边一列即为各个货币对的点差值。由于点差的存在,因此买卖任何货币对都会有一个初始的损失,该损失即为该货币对的交易成本。
1. 公式
根据上文中公式(1)、(2)、(3)、(4)可将交易成本概括为以下三种情况:
1) 利润货币的直盘货币对基础货币为账户货币
以美元账户为示例,例如:USDJPY,EURJPY,利润货币都为JPY,JPY的直盘货币对为USDJPY,USDJPY的基础货币为账户货币USD,
这种情况下点差产生的交易成本是: (公式5)
其中:
- Lots:交易手数
- ContractSize:一标准手合约大小,外汇品种为100,000基础货币
- SymbPoint:该货币对波动最小点
- Spread:该货币对点差
- Price:利润货币的直盘货币对的当前价格。
2) 利润货币为账户货币
以美元账户为示例,例如:EURUSD,GBPUSD等
这种情况下点差产生的交易成本是: (公式6)
3) 利润货币的直盘货币对基础货币非账户货币
以美元账户为示例,例如:EURGBP,GBPAUD等
这种情况下点差产生的交易成本是: (公式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)可以转化为,
因此在CSpreadCost::GetSpread() 中,将公式(5)、(7)对应的交易成本计算方法统一成为一个公式。
由于平台中可能会没有利润货币的直盘货币对的报价,例如在英镑账户中,USDHKD的利润货币为港币HKD,因为账户货币为GBP,所以其直盘货币对应为GBPHKD,而平台中可能没有GBPHKD的直接报价,对此作出如下处理:
利润货币与美元的报价中,美元为基础货币;账户货币与美元的报价中,美元为基础货币。此时有:
利润货币与美元的报价中,美元为基础货币;账户货币与美元的报价中,账户货币为基础货币。此时有:
利润货币与美元的报价中,利润货币为基础货币;账户货币与美元的报价中,美元为基础货币。此时有:
- 利润货币与美元的报价中,利润货币为基础货币;账户货币与美元的报价中,账户货币为基础货币。此时有:
其中: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()用于判断平台里是否有指定货币对的报价。