CoolFace
Apppublic

Ankit3445/options_pricing

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
Strategy.cpp195 linesDownload Raw Back to root
1#include "Strategy.hpp"2#include <cmath>3#include <sstream>4#include <algorithm>5#include <numeric>6 7double StrategyBuilder::norm_cdf(double x) {8    return 0.5 * (1.0 + std::erf(x / std::sqrt(2.0)));9}10 11double StrategyBuilder::bs_price(double S, double K, double T, double r, double sigma, OptionType type) {12    double d1 = (std::log(S / K) + (r + sigma * sigma * 0.5) * T) / (sigma * std::sqrt(T));13    double d2 = d1 - sigma * std::sqrt(T);14    if (type == OptionType::CALL)15        return S * norm_cdf(d1) - K * std::exp(-r * T) * norm_cdf(d2);16    else17        return K * std::exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1);18}19 20Greeks StrategyBuilder::bs_greeks(double S, double K, double T, double r, double sigma, OptionType type) {21    Greeks g;22    if (T <= 0.0 || sigma <= 0.0) { g.valid = false; return g; }23    double d1 = (std::log(S / K) + (r + sigma * sigma * 0.5) * T) / (sigma * std::sqrt(T));24    double d2 = d1 - sigma * std::sqrt(T);25    double pdf = std::exp(-0.5 * d1 * d1) / std::sqrt(2.0 * M_PI);26    if (type == OptionType::CALL) {27        g.price = S * norm_cdf(d1) - K * std::exp(-r * T) * norm_cdf(d2);28        g.delta = norm_cdf(d1);29        g.gamma = pdf / (S * sigma * std::sqrt(T));30        g.vega  = S * pdf * std::sqrt(T) / 100.0;31        g.theta = (-S * pdf * sigma / (2.0 * std::sqrt(T)) - r * K * std::exp(-r * T) * norm_cdf(d2)) / 365.0;32        g.rho   = K * T * std::exp(-r * T) * norm_cdf(d2) / 100.0;33    } else {34        g.price = K * std::exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1);35        g.delta = norm_cdf(d1) - 1.0;36        g.gamma = pdf / (S * sigma * std::sqrt(T));37        g.vega  = S * pdf * std::sqrt(T) / 100.0;38        g.theta = (-S * pdf * sigma / (2.0 * std::sqrt(T)) + r * K * std::exp(-r * T) * norm_cdf(-d2)) / 365.0;39        g.rho   = -K * T * std::exp(-r * T) * norm_cdf(-d2) / 100.0;40    }41    g.impliedVol = sigma;42    g.valid = true;43    return g;44}45 46// ── Strategy Factories ──47StrategyDef StrategyBuilder::covered_call(const std::string& ticker, double spot, double strike, double expiry) {48    double sigma = 0.25;49    StrategyDef s;50    s.name = "Covered Call"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;51    s.legs = {{strike, expiry, OptionType::CALL, -1, bs_price(spot, strike, expiry, 0.04, sigma, OptionType::CALL)}};52    return s;53}54 55StrategyDef StrategyBuilder::protective_put(const std::string& ticker, double spot, double strike, double expiry) {56    double sigma = 0.25;57    StrategyDef s;58    s.name = "Protective Put"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;59    s.legs = {{strike, expiry, OptionType::PUT, 1, bs_price(spot, strike, expiry, 0.04, sigma, OptionType::PUT)}};60    return s;61}62 63StrategyDef StrategyBuilder::straddle(const std::string& ticker, double spot, double strike, double expiry) {64    double sigma = 0.25;65    StrategyDef s;66    s.name = "Straddle"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;67    s.legs = {68        {strike, expiry, OptionType::CALL, 1, bs_price(spot, strike, expiry, 0.04, sigma, OptionType::CALL)},69        {strike, expiry, OptionType::PUT,  1, bs_price(spot, strike, expiry, 0.04, sigma, OptionType::PUT)}70    };71    return s;72}73 74StrategyDef StrategyBuilder::strangle(const std::string& ticker, double spot, double low_strike, double high_strike, double expiry) {75    double sigma = 0.25;76    StrategyDef s;77    s.name = "Strangle"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;78    s.legs = {79        {low_strike,  expiry, OptionType::PUT,  1, bs_price(spot, low_strike, expiry, 0.04, sigma, OptionType::PUT)},80        {high_strike, expiry, OptionType::CALL, 1, bs_price(spot, high_strike, expiry, 0.04, sigma, OptionType::CALL)}81    };82    return s;83}84 85StrategyDef StrategyBuilder::bull_call_spread(const std::string& ticker, double spot, double low_strike, double high_strike, double expiry) {86    double sigma = 0.25;87    StrategyDef s;88    s.name = "Bull Call Spread"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;89    s.legs = {90        {low_strike,  expiry, OptionType::CALL, 1, bs_price(spot, low_strike, expiry, 0.04, sigma, OptionType::CALL)},91        {high_strike, expiry, OptionType::CALL, -1, bs_price(spot, high_strike, expiry, 0.04, sigma, OptionType::CALL)}92    };93    return s;94}95 96StrategyDef StrategyBuilder::bear_put_spread(const std::string& ticker, double spot, double low_strike, double high_strike, double expiry) {97    double sigma = 0.25;98    StrategyDef s;99    s.name = "Bear Put Spread"; s.ticker = ticker; s.spot = spot; s.rate = 0.04;100    s.legs = {101        {high_strike, expiry, OptionType::PUT, 1, bs_price(spot, high_strike, expiry, 0.04, sigma, OptionType::PUT)},102        {low_strike,  expiry, OptionType::PUT, -1, bs_price(spot, low_strike, expiry, 0.04, sigma, OptionType::PUT)}103    };104    return s;105}106 107StrategyDef StrategyBuilder::butterfly(const std::string& ticker, double spot, double low, double mid, double high, double expiry) {108    double sigma = 0.25;109    double r = 0.04;110    StrategyDef s;111    s.name = "Butterfly"; s.ticker = ticker; s.spot = spot; s.rate = r;112    s.legs = {113        {low,  expiry, OptionType::CALL, 1,  bs_price(spot, low, expiry, r, sigma, OptionType::CALL)},114        {mid,  expiry, OptionType::CALL, -2, bs_price(spot, mid, expiry, r, sigma, OptionType::CALL)},115        {high, expiry, OptionType::CALL, 1,  bs_price(spot, high, expiry, r, sigma, OptionType::CALL)}116    };117    return s;118}119 120StrategyDef StrategyBuilder::iron_condor(const std::string& ticker, double spot, double put_low, double put_high, double call_low, double call_high, double expiry) {121    double sigma = 0.25;122    double r = 0.04;123    StrategyDef s;124    s.name = "Iron Condor"; s.ticker = ticker; s.spot = spot; s.rate = r;125    s.legs = {126        {put_low,  expiry, OptionType::PUT,  -1, bs_price(spot, put_low, expiry, r, sigma, OptionType::PUT)},127        {put_high, expiry, OptionType::PUT,  1,  bs_price(spot, put_high, expiry, r, sigma, OptionType::PUT)},128        {call_low, expiry, OptionType::CALL, 1,  bs_price(spot, call_low, expiry, r, sigma, OptionType::CALL)},129        {call_high,expiry, OptionType::CALL, -1, bs_price(spot, call_high, expiry, r, sigma, OptionType::CALL)}130    };131    return s;132}133 134Greeks StrategyBuilder::greeks_at_spot(const StrategyDef& strat, double spot) {135    Greeks combined;136    double sigma = 0.25;137    for (const auto& leg : strat.legs) {138        Greeks g = bs_greeks(spot, leg.strike, leg.expiry, strat.rate, sigma, leg.type);139        combined.price  += g.price * leg.quantity;140        combined.delta  += g.delta * leg.quantity;141        combined.gamma  += g.gamma * leg.quantity;142        combined.vega   += g.vega * leg.quantity;143        combined.theta  += g.theta * leg.quantity;144        combined.rho    += g.rho * leg.quantity;145    }146    combined.valid = true;147    return combined;148}149 150nlohmann::json StrategyBuilder::pnl_at_expiry(const StrategyDef& strat, double spot_min, double spot_max, int steps) {151    double total_cost = 0.0;152    for (const auto& leg : strat.legs)153        total_cost += leg.entry_price * leg.quantity;154 155    nlohmann::json data = nlohmann::json::array();156    double step = (spot_max - spot_min) / steps;157    for (int i = 0; i <= steps; ++i) {158        double S = spot_min + i * step;159        // At expiry, option value = intrinsic value160        double pnl = -total_cost;161        for (const auto& leg : strat.legs) {162            double intrinsic = 0.0;163            if (leg.type == OptionType::CALL)164                intrinsic = std::max(S - leg.strike, 0.0);165            else166                intrinsic = std::max(leg.strike - S, 0.0);167            pnl += intrinsic * leg.quantity;168        }169        Greeks g = greeks_at_spot(strat, S);170        data.push_back({{"spot", S}, {"pnl", pnl}, {"delta", g.delta}, {"gamma", g.gamma}});171    }172    return data;173}174 175nlohmann::json StrategyBuilder::to_json(const StrategyDef& strat) {176    nlohmann::json legs = nlohmann::json::array();177    double total_cost = 0.0;178    for (const auto& leg : strat.legs) {179        total_cost += leg.entry_price * leg.quantity;180        legs.push_back({181            {"strike", leg.strike}, {"expiry", leg.expiry},182            {"type", leg.type == OptionType::CALL ? "CALL" : "PUT"},183            {"qty", leg.quantity}, {"entry_price", leg.entry_price}184        });185    }186    Greeks g = greeks_at_spot(strat, strat.spot);187    return {188        {"name", strat.name}, {"ticker", strat.ticker}, {"spot", strat.spot},189        {"legs", legs}, {"total_cost", total_cost},190        {"price", g.price}, {"delta", g.delta}, {"gamma", g.gamma},191        {"vega", g.vega}, {"theta", g.theta}, {"rho", g.rho},192        {"pnl_data", pnl_at_expiry(strat, strat.spot * 0.5, strat.spot * 1.5, 50)}193    };194}195