TextWidget::TextWidget( SUnit height, SVec p, Widget* parent, const std::string& t, const SORE_Graphics::Color& c) : Widget(SVec(SUnit(), height), p, parent), color(c) { face = fontCache.Get(Style()["TextWidget"]["font"].asString()); material = materialCache.Clone(Style()["TextWidget"]["material"].asString()); SetText(t); }
void ContinuousArithmeticAsianVecerEngine::calculate() const { Real expectedAverage; QL_REQUIRE(arguments_.averageType == Average::Arithmetic, "not an Arithmetic average option"); QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "not an European Option"); DayCounter rfdc = process_->riskFreeRate()->dayCounter(); DayCounter divdc = process_->dividendYield()->dayCounter(); DayCounter voldc = process_->blackVolatility()->dayCounter(); Real S_0 = process_->stateVariable()->value(); // payoff ext::shared_ptr<StrikedTypePayoff> payoff = ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); QL_REQUIRE(payoff, "non-plain payoff given"); // original time to maturity Date maturity = arguments_.exercise->lastDate(); Real X = payoff->strike(); QL_REQUIRE(z_min_<=0 && z_max_>=0, "strike (0 for vecer fixed strike asian) not on Grid"); Volatility sigma = process_->blackVolatility()->blackVol(maturity, X); Rate r = process_->riskFreeRate()-> zeroRate(maturity, rfdc, Continuous, NoFrequency); Rate q = process_->dividendYield()-> zeroRate(maturity, divdc, Continuous, NoFrequency); Date today(Settings::instance().evaluationDate()); QL_REQUIRE(startDate_>=today, "Seasoned Asian not yet implemented"); // Expiry in Years Time T = rfdc.yearFraction(today, arguments_.exercise->lastDate()); Time T1 = rfdc.yearFraction(today, startDate_ ); // Average Begin Time T2 = T; // Average End (In this version only Maturity...) if ((T2 - T1) < 0.001) { // its a vanilla option. Use vanilla engine VanillaOption europeanOption(payoff, arguments_.exercise); europeanOption.setPricingEngine( ext::make_shared<AnalyticEuropeanEngine>(process_)); results_.value = europeanOption.NPV(); } else { Real Theta = 0.5; // Mixed Scheme: 0.5 = Crank Nicolson Real Z_0 = cont_strategy(0,T1,T2,q,r) - std::exp(-r*T) * X /S_0; QL_REQUIRE(Z_0>=z_min_ && Z_0<=z_max_, "spot not on grid"); Real h = (z_max_ - z_min_) / assetSteps_; // Space step size Real k = T / timeSteps_; // Time Step size Real sigma2 = sigma * sigma, vecerTerm; Array SVec(assetSteps_+1),u_initial(assetSteps_+1), u(assetSteps_+1),rhs(assetSteps_+1); for (Natural i= 0; i<= SVec.size()-1;i++) { SVec[i] = z_min_ + i * h; // Value of Underlying on the grid } // Begin gamma construction TridiagonalOperator gammaOp = DPlusDMinus(assetSteps_+1,h); Array upperD = gammaOp.upperDiagonal(); Array lowerD = gammaOp.lowerDiagonal(); Array Dia = gammaOp.diagonal(); // Construct Vecer operator TridiagonalOperator explicit_part(gammaOp.size()); TridiagonalOperator implicit_part(gammaOp.size()); for (Natural i= 0; i<= SVec.size()-1;i++) { u_initial[i] = std::max<Real>(SVec[i] , 0.0); // Call Payoff } u = u_initial; // Start Time Loop for (Natural j = 1; j<=timeSteps_;j++) { if (Theta != 1.0) { // Explicit Part for (Natural i = 1; i<= SVec.size()-2;i++) { vecerTerm = SVec[i] - std::exp(-q * (T-(j-1)*k)) * cont_strategy(T-(j-1)*k,T1,T2,q,r); gammaOp.setMidRow(i, 0.5 * sigma2 * vecerTerm * vecerTerm * lowerD[i-1], 0.5 * sigma2 * vecerTerm * vecerTerm * Dia[i], 0.5 * sigma2 * vecerTerm * vecerTerm * upperD[i]); } explicit_part = gammaOp.identity(gammaOp.size()) + (1 - Theta) * k * gammaOp; explicit_part.setFirstRow(1.0,0.0); // Apply before applying explicit_part.setLastRow(-1.0,1.0); // Neumann BC u = explicit_part.applyTo(u); // Apply after applying (Neumann BC) u[assetSteps_] = u[assetSteps_-1] + h; u[0] = 0; } // End Explicit Part if (Theta != 0.0) { // Implicit Part for (Natural i = 1; i<= SVec.size()-2;i++) { vecerTerm = SVec[i] - std::exp(-q * (T-j*k)) * cont_strategy(T-j*k,T1,T2,q,r); gammaOp.setMidRow(i, 0.5 * sigma2 * vecerTerm * vecerTerm * lowerD[i-1], 0.5 * sigma2 * vecerTerm * vecerTerm * Dia[i], 0.5 * sigma2 * vecerTerm * vecerTerm * upperD[i]); } implicit_part = gammaOp.identity(gammaOp.size()) - Theta * k * gammaOp; // Apply before solving implicit_part.setFirstRow(1.0,0.0); implicit_part.setLastRow(-1.0,1.0); rhs = u; rhs[0] = 0; // Lower BC rhs[assetSteps_] = h; // Upper BC (Neumann) Delta=1 u = implicit_part.solveFor(rhs); } // End implicit Part } // End Time Loop DownRounding Rounding(0); Integer lowerI = Integer(Rounding( (Z_0-z_min_)/h)); // Interpolate solution Real pv; pv = u[lowerI] + (u[lowerI+1] - u[lowerI]) * (Z_0 - SVec[lowerI])/h; results_.value = S_0 * pv; if (payoff->optionType()==Option::Put) { // Apply Call Put Parity for Asians if (r == q) { expectedAverage = S_0; } else { expectedAverage = S_0 * (std::exp( (r-q) * T2) - std::exp( (r-q) * T1)) / ((r-q) * (T2-T1)); } Real asianForward = std::exp(-r * T2) * (expectedAverage - X); results_.value = results_.value - asianForward; } } }
void TextWidget::SetText(const std::string& t) { text = t; unsigned int h = static_cast<unsigned int>(GetSize(VERTICAL)); SetSize(SVec(SUnit(static_cast<int>(face->Width(h, text))), GetSize().GetVertical())); }