Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ Intraday bars: 1m / 5m / 15m / 30m / 1H / 4H / 1D. 15 metrics + benchmark compar
</details>

<details>
<summary><b>Quant Library</b> <sub>286 tested functions across 19 modules, callable from every transport</sub></summary>
<summary><b>Quant Library</b> <sub>287 tested functions across 19 modules, callable from every transport</sub></summary>

`src/quantlib` holds one tested implementation of each piece of finance math the
agent needs. Skills **import** these rather than carrying formulas inside
Expand Down
2 changes: 1 addition & 1 deletion README_ar.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ LONGBRIDGE_ACCESS_TOKEN=...
</details>

<details>
<summary><b>Quant Library</b> <sub>286 دالة مختبَرة عبر 19 وحدة، قابلة للاستدعاء من كل المسارات</sub></summary>
<summary><b>Quant Library</b> <sub>287 دالة مختبَرة عبر 19 وحدة، قابلة للاستدعاء من كل المسارات</sub></summary>

يحتفظ `src/quantlib` بتنفيذ مختبَر **واحد فقط** لكل قطعة من الرياضيات المالية التي
يحتاجها الـ agent. صارت الـ skills **تستورد** هذه الدوال بدلاً من حمل الصيغ داخل كتل
Expand Down
2 changes: 1 addition & 1 deletion README_es.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ Barras intradía: 1m / 5m / 15m / 30m / 1H / 4H / 1D. 15 métricas + comparació
</details>

<details>
<summary><b>Quant Library</b> <sub>286 funciones probadas en 19 módulos, invocables desde cualquier transporte</sub></summary>
<summary><b>Quant Library</b> <sub>287 funciones probadas en 19 módulos, invocables desde cualquier transporte</sub></summary>

`src/quantlib` contiene una implementación probada de cada pieza de matemática
financiera que el agente necesita. Las skills **importan** estas funciones en
Expand Down
2 changes: 1 addition & 1 deletion README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ Intraday bars: 1m / 5m / 15m / 30m / 1H / 4H / 1D. 15 metrics + benchmark compar
</details>

<details>
<summary><b>Quant Library</b> <sub>19 モジュール・286 個のテスト済み関数、すべての経路から呼び出し可能</sub></summary>
<summary><b>Quant Library</b> <sub>19 モジュール・287 個のテスト済み関数、すべての経路から呼び出し可能</sub></summary>

`src/quantlib` は、agent が必要とする金融数学のそれぞれについて、テスト済みの実装を
**1 つだけ**保持します。skill はこれらを **import** するようになり、markdown コード
Expand Down
2 changes: 1 addition & 1 deletion README_ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ Intraday bars: 1m / 5m / 15m / 30m / 1H / 4H / 1D. 15 metrics + benchmark compar
</details>

<details>
<summary><b>Quant Library</b> <sub>19개 모듈 286개의 테스트된 함수, 모든 경로에서 호출 가능</sub></summary>
<summary><b>Quant Library</b> <sub>19개 모듈 287개의 테스트된 함수, 모든 경로에서 호출 가능</sub></summary>

`src/quantlib`는 agent가 필요로 하는 각 금융 수학에 대해 테스트된 구현을 **하나씩만**
보유합니다. skill은 이제 이 함수들을 **import**하며, markdown 코드 블록 안에 수식을
Expand Down
2 changes: 1 addition & 1 deletion README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ LONGBRIDGE_ACCESS_TOKEN=...
</details>

<details>
<summary><b>Quant Library</b> <sub>19 个模块 286 个经测试的函数,四条通路皆可调用</sub></summary>
<summary><b>Quant Library</b> <sub>19 个模块 287 个经测试的函数,四条通路皆可调用</sub></summary>

`src/quantlib` 为 agent 需要的每一块金融数学各提供**一份**经测试的实现。skill 现在是
**import** 这些函数,而不再把公式抄在 markdown 代码块里——如果你在某个 `SKILL.md`
Expand Down
67 changes: 67 additions & 0 deletions agent/src/quantlib/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

__all__ = [
"BARRIER_TYPES",
"barrier_greeks",
"barrier_option_price",
"bs_greeks",
"bs_price",
Expand Down Expand Up @@ -633,3 +634,69 @@ def barrier_option_price(
raise ValueError(f"Unhandled barrier type {b_type}")

return float(max(0.0, price))



def barrier_greeks(
S: float,
K: float,
H: float,
T: float,
r: float,
sigma: float,
barrier_type: str,
option_type: str = "call",
q: float = 0.0,
rebate: float = 0.0,
) -> dict[str, float]:
"""Compute sensitivity Greeks for single-barrier options via central finite differences.

Matches the conventions of :func:`bs_greeks`:
* delta: per 1.0 of spot
* gamma: per 1.0 of spot squared
* theta: per calendar day (1/365)
* vega: per 1 percentage point of volatility (0.01)
* rho: per 1 percentage point of interest rate (0.01)

Args:
S, K, H, T, r, sigma, barrier_type, option_type, q, rebate: Standard barrier inputs.

Returns:
dict with keys: ``delta``, ``gamma``, ``theta``, ``vega``, ``rho``.
"""
p = barrier_option_price(S, K, H, T, r, sigma, barrier_type, option_type, q, rebate)

dS = max(1e-4, 1e-4 * S)
p_up = barrier_option_price(S + dS, K, H, T, r, sigma, barrier_type, option_type, q, rebate)
p_down = barrier_option_price(S - dS, K, H, T, r, sigma, barrier_type, option_type, q, rebate)

delta = float((p_up - p_down) / (2.0 * dS))
gamma = float((p_up - 2.0 * p + p_down) / (dS**2))

# Theta (per calendar day): time decay moves forward, so T - dt
dt = 1.0 / 365.0
if T > dt:
p_dt = barrier_option_price(S, K, H, T - dt, r, sigma, barrier_type, option_type, q, rebate)
theta = float(p_dt - p)
else:
theta = 0.0

# Vega (per 1 percentage point = 0.01)
dvol = 1e-4
p_vol_up = barrier_option_price(S, K, H, T, r, sigma + dvol, barrier_type, option_type, q, rebate)
p_vol_down = barrier_option_price(S, K, H, T, r, max(1e-6, sigma - dvol), barrier_type, option_type, q, rebate)
vega = float((p_vol_up - p_vol_down) / (2.0 * dvol) * 0.01)

# Rho (per 1 percentage point = 0.01)
dr = 1e-4
p_r_up = barrier_option_price(S, K, H, T, r + dr, sigma, barrier_type, option_type, q, rebate)
p_r_down = barrier_option_price(S, K, H, T, r - dr, sigma, barrier_type, option_type, q, rebate)
rho = float((p_r_up - p_r_down) / (2.0 * dr) * 0.01)

return {
"delta": delta,
"gamma": gamma,
"theta": theta,
"vega": vega,
"rho": rho,
}
14 changes: 12 additions & 2 deletions agent/tests/quantlib/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
import pytest

from src.quantlib.options import (
BARRIER_TYPES,
barrier_greeks,
barrier_option_price,
bs_greeks,
bs_price,
implied_volatility,
normalise_barrier_type,
normalise_option_type,
)

Expand Down Expand Up @@ -560,6 +559,17 @@ def test_already_breached_barrier_behavior(self):
assert barrier_option_price(85.0, 100.0, 90.0, 0.5, 0.05, 0.20, "down-and-in", "call") == pytest.approx(
vanilla
)
def test_barrier_greeks_far_from_barrier_matches_bs_greeks(self):
# When barrier H is far away (e.g. down barrier H=10 when S=100), barrier call greeks ~ vanilla call greeks
S, K, H, T, r, sigma = 100.0, 100.0, 10.0, 1.0, 0.05, 0.20
bg = barrier_greeks(S, K, H, T, r, sigma, "down-and-out", "call")
vg = bs_greeks(S, K, T, r, sigma, "call")

assert bg["delta"] == pytest.approx(vg["delta"], abs=5e-3)
assert bg["gamma"] == pytest.approx(vg["gamma"], abs=5e-3)
assert bg["vega"] == pytest.approx(vg["vega"], abs=5e-3)
assert bg["theta"] == pytest.approx(vg["theta"], abs=5e-3)
assert bg["rho"] == pytest.approx(vg["rho"], abs=5e-3)

def test_barrier_option_input_validation(self):
with pytest.raises(ValueError, match="strictly positive"):
Expand Down