A simple FX-Option Example in QuantLib
Originally published September 2009, updated 10 May 2020 (move to Jekyll, add the link to online calculator.)
An online, Python, QuantPanel version of this calculation is available at http://quantpanel.bnikolic.co.uk/FxOption.
Here is a simple, bare-bones example of pricing an American FX vanilla option in QuantLib:
/**
   Copyright (C) 2008, 2009 Bojan Nikolic <bojan@bnikolic.co.uk>
   Simple bare-bones example of using QuantLib to price an FX option
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the license for more details.
   Comments welcome at bojan@bnikolic.co.uk
*/
#include <iostream>
#include <ql/quantlib.hpp>
struct OptionInputs 
{
  QuantLib::Real S;
  QuantLib::Real K;
  /// Foreign rate
  QuantLib::Spread f;
  /// Domestic rate
  QuantLib::Rate r;
  QuantLib::Volatility vol;
  QuantLib::Date maturity;
  QuantLib::DayCounter dayCounter;
};
double 
CRRPricing(QuantLib::VanillaOption &o,
	   boost::shared_ptr<QuantLib::GarmanKohlagenProcess> process,
	   QuantLib::Size timeSteps)
{
  using namespace QuantLib;
  boost::shared_ptr<PricingEngine> pe(new BinomialVanillaEngine<CoxRossRubinstein>(process,
										   timeSteps));
  o.setPricingEngine(pe);
  return o.NPV();
}
void FxOptEx(const OptionInputs &in,
	     const QuantLib::Date &todaysDate,
	     const QuantLib::Date &settlementDate)
{
  using namespace QuantLib;
  
  // set up dates
  Calendar calendar = TARGET();
  Settings::instance().evaluationDate() = todaysDate;
  boost::shared_ptr<Exercise> 
    americanExercise(new AmericanExercise(settlementDate,
					  in.maturity));
  
  Handle<Quote>
    underlyingH(boost::shared_ptr<Quote>(new SimpleQuote(in.S)));
  
  Handle<YieldTermStructure> 
    rTS(boost::shared_ptr<YieldTermStructure>(new FlatForward(settlementDate, 
							      in.r, 
							      in.dayCounter)));
  Handle<YieldTermStructure> 
    fTS(boost::shared_ptr<YieldTermStructure>(new FlatForward(settlementDate, 
							      in.f, 
							      in.dayCounter)));
  Handle<BlackVolTermStructure> 
    flatVolTS(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(settlementDate, 
									    calendar, 
									    in.vol,
									    in.dayCounter)));
  boost::shared_ptr<StrikedTypePayoff> 
    payoff(new PlainVanillaPayoff(Option::Call, 
				  in.K));
  
  boost::shared_ptr<GarmanKohlagenProcess> 
    process(new GarmanKohlagenProcess(underlyingH, 
				      fTS,
				      rTS, 
				      flatVolTS));
  
  VanillaOption amerOpt(payoff,
			americanExercise);
  
  double npv=CRRPricing(amerOpt,
			process,
			100);
  std::cout<<"Option value:"
	   <<npv
	   <<std::endl;
}
int main(int, char* []) 
{
  using namespace QuantLib;
  OptionInputs in;
  in.S=100;
  in.K=100;
  in.f=0.05;
  in.r=0.02;
  in.vol=0.20;
  in.maturity= Date(17, May, 1999);
  in.dayCounter = Actual365Fixed();  
  FxOptEx(in,
	  Date(15, May, 1998),
	  Date(17, May, 1998));
}