所谓的swap(掉期交易)是指两家公司相互交换未来现金流的协议,这份协议定义了现金流支付的日期以及计算的方法,通常现金流的计算会涉及利率、汇率,或者其他市场变量的预期值。
(例1)远期合约是一种简单形式的swap。比如,在2009年3月1日,公司A以900美元/盎司的价格买入100盎司的一年远期黄金。它可以在收到这一年期黄金的时候立即抛出。这样的远期合约就相当于是一个swap,即这家公司同意它会在2010年3月1日支付90000美元并收到100S美元,这里的S是2010年3月1日这一天一盎司黄金的市场单价。
远期合约相当于在未来的某一天交换现金流,而swap通常会在多个未来日子进行交换。
最常见的swap类型是所谓的“plain vanilla” interest rate swap,利率掉期交易。公司A同意以固定利率在几年之内为一定的本金支付现金流(也就是利息),作为回报,它会在同样时期内得到同样本金上浮动利率的现金流。绝大多数利率掉期采用的浮动利率都是伦敦同业拆放利率(LIBOR)。LIBOR是国际金融市场上借贷的参考利率,通常LIBOR会以各大主要货币的形式提供1、3、6、12个月的利率。比如(例2),一个5年期的债券可以规定其票息率为6个月的LIBOR加0.5%年息。这样,这个债券就被分成十个阶段,利率是每个阶段一开始时6个月LIBOR利率加0.5%年息,并在这个阶段结束时支付。
(例3)假设微软和英特尔在2007年3月5日设立了一个3年的swap。微软答应以一亿美元(100million)为本金principal,向英特尔支付5%的年息,作为回报,英特尔答应向微软支付以同数额为本金的LIBOR利率,每半年支付一次。在这里微软是固定利率支付方fixed-rate payer,而英特尔是浮动利率支付方floating-rate payer。这样,第一次支付日期将是2007年9月5日,微软要支付的金额是2.5million,英特尔要支付的是这个日期的六个月之前的LIBOR利率,假设为4.2%,因此就是0.5*0.042*100million = 2.1million。注意这次付款金额是确定的,因为在签订合约的时候,LIBOR就已经确定下来了。第二次支付日期是2008年3月5日,微软要支付2.5million,英特尔要支付2007年9月5日的LIBOR利率,假设为4.8%,因此是0.5*0.048*100million = 2.4million。如此一共要支付6次。注意,本金在这里只是名义上的(notional),双方并不会真的支付它们。这个swap也可以看作是固定利率债券和浮动利率债券的交换。
因此,swap可以将浮动利率的现金流和固定利率的现金流对调,让双方规避风险或者最大化利益。通常会有一个中间商(比如银行)从中协调并抽取佣金,同时承担其中一方无法履行合约的风险。由于不同信用评级的公司/国家在国际市场上借贷时的利率是不一样的,因此swap可以帮助交换双方找到最适合自己的方式。
#include <ql/instrument.hpp>
#include <ql/cashflow.hpp>
class Event : public Observable {
public:
virtual ~Event() {}
virtual Date date() const = 0;
// 若event在date之前发生则返回true。如果includeRefDate为真,那么在date等于refDate的情况下,认为event未发生,即返回false
virtual bool hasOccurred(const Date &refDate = Date(), boost::optional<bool> includeRefDate = boost::none) const;
virtual void accept(AcyclicVisitor&);
};
class CashFlow : public Event {
public:
virtual ~CashFlow() {}
virtual Date date() const = 0;
virtual bool hasOccurred(const Date &refDate = Date(), boost::optional<bool> includeRefDate = boost::none) const;
// this is the amount paid on the cash flow date, it is not discounted.
virtual Real amount() const = 0;
virtual void accept(AcyclicVisitor&);
};
typedef std::vector<boost::shared_ptr<CashFlow> > Leg;
class Swap : public Instrument {
public:
class arguments;
class results;
class engine;
// first leg's cash flows are paid, while the second leg's cash flows are received.
Swap(const Leg &firstLeg, const Leg &secondLeg);
Swap(const std::vector<Leg> &legs, const std::vector<bool> &payer);
bool isExpired() const;
void setupArguments(PricingEngine::arguments*) const;
void fetchResults(const PricingEngine::results*) const;
Date startDate() const;
Date maturityDate() const;
Real legBPS(Size j) const {
QL_REQUIRE(j<legs_.size(), "leg# "<<j<<" doesn't exist!");
calculate();
return legBPS_[j];
}
Real legNPV(Size j) const {
QL_REQUIRE(j<legs_.size(), "leg# "<<j<<" doesn't exist!");
calculate();
return legNPV_[j];
}
const Leg& leg(Size j) const {
QL_REQUIRE(j<legs_.size(), "leg# "<<j<<" doesn't exist!");
return legs_[j];
}
protected:
Swap(Size legs);
void setupExpired() const;
std::vector<Leg> legs_;
std::vector<Real> payer_;
mutable std::vector<Real> legNPV_;
mutable std::vector<Real> legBPS_;
};
class Swap::arguments : public virtual PricingEngine::arguments {
public:
std::vector<Leg> legs;
std::vector<Real> payer;
void validate() const;
};
class Swap::results : public Instrument::results {
public:
std::vector<Real> legNPV;
std::vector<Real> legBPS;
void reset();
};
class Swap::engine : public GenericEngine<Swap::arguments, Swap::results> {};
- 这里的CashFlow是Visitor模式的client,具体关于Acyclic Visitor的信息可以在这里找到。
// 首先将Swap注册成为两条Leg的observer,这样在它们发生变化的时候就可以触发重新计算
Swap::Swap(const Leg& firstLeg, const Leg& secondLeg) : legs_(2), payer_(2), legNPV_(2, 0.0), legBPS_(2, 0.0) {
legs_[0] = firstLeg;
legs_[1] = secondLeg;
payer_[0] = -1.0;
payer_[1] = 1.0;
for (Leg::iterator i = legs_[0].begin(); i!= legs_[0].end(); ++i)
registerWith(*i);
for (Leg::iterator i = legs_[1].begin(); i!= legs_[1].end(); ++i)
registerWith(*i);
}
// 只要Leg里有CashFlow还未发生,那么就返回false表示没有过期。
bool Swap::isExpired() const {
for (Size j=0; j<legs_.size(); ++j) {
Leg::const_iterator i;
for (i = legs_[j].begin(); i!= legs_[j].end(); ++i)
if (!(*i)->hasOccurred())
return false;
}
return true;
}
void Swap::setupExpired() const {
Instrument::setupExpired();
std::fill(legBPS_.begin(), legBPS_.end(), 0.0);
std::fill(legNPV_.begin(), legNPV_.end(), 0.0);
}
cont.