173 lines
9.7 KiB
HTML
173 lines
9.7 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="en" data-bs-theme="dark">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8" />
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|||
|
|
<title>Settings — Options Pricer</title>
|
|||
|
|
<link rel="stylesheet" href="/assets/tabler.min.css" />
|
|||
|
|
<link rel="stylesheet" href="/assets/tabler-vendors.min.css" />
|
|||
|
|
<style>
|
|||
|
|
.mono { font-family:'JetBrains Mono','Fira Code',monospace; }
|
|||
|
|
[x-cloak] { display:none !important; }
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body class="antialiased">
|
|||
|
|
<div class="wrapper" x-data="settingsApp()" x-init="init()">
|
|||
|
|
|
|||
|
|
<!-- Sidebar -->
|
|||
|
|
<aside class="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark">
|
|||
|
|
<div class="container-fluid">
|
|||
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sb-menu"><span class="navbar-toggler-icon"></span></button>
|
|||
|
|
<h1 class="navbar-brand navbar-brand-autodark">
|
|||
|
|
<a href="index.html" class="text-decoration-none d-flex align-items-center gap-2">
|
|||
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><rect x="4" y="8" width="4" height="8" rx="1"/><line x1="6" y1="4" x2="6" y2="8"/><line x1="6" y1="16" x2="6" y2="20"/><rect x="16" y="6" width="4" height="10" rx="1"/><line x1="18" y1="2" x2="18" y2="6"/><line x1="18" y1="16" x2="18" y2="22"/></svg>
|
|||
|
|
<span class="fw-bold">Options Pricer</span>
|
|||
|
|
</a>
|
|||
|
|
</h1>
|
|||
|
|
<div class="collapse navbar-collapse" id="sb-menu">
|
|||
|
|
<ul class="navbar-nav pt-lg-3">
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="index.html"><span class="nav-link-title">Dashboard</span></a></li>
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="chain.html"><span class="nav-link-title">Options Chain</span></a></li>
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="surface.html"><span class="nav-link-title">Vol Surface</span></a></li>
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="strategy.html"><span class="nav-link-title">Strategy P/L</span></a></li>
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="positions.html"><span class="nav-link-title">Positions</span></a></li>
|
|||
|
|
<li class="nav-item"><a class="nav-link" href="tracker.html"><span class="nav-link-title">Tracker</span></a></li>
|
|||
|
|
<li class="nav-item active"><a class="nav-link" href="settings.html"><span class="nav-link-title">Settings</span></a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
<!-- Page -->
|
|||
|
|
<div class="page-wrapper">
|
|||
|
|
<div class="page-header d-print-none">
|
|||
|
|
<div class="container-xl">
|
|||
|
|
<div class="row g-2 align-items-center">
|
|||
|
|
<div class="col"><h2 class="page-title">Settings</h2></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="page-body">
|
|||
|
|
<div class="container-xl">
|
|||
|
|
|
|||
|
|
<div class="card mb-3" style="background:#161824; border:1px solid #2d3045;">
|
|||
|
|
<div class="card-header" style="border-bottom:1px solid #2d3045;">
|
|||
|
|
<h3 class="card-title text-white mb-0">Options Commission</h3>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-body">
|
|||
|
|
<p class="text-secondary small mb-3">
|
|||
|
|
Used when computing Net P/L on the <a href="positions.html">Positions</a> page.
|
|||
|
|
Defaults match <strong>Interactive Brokers Fixed / IBKR Lite</strong> for US equity options:
|
|||
|
|
<span class="mono">$0.65 per contract, $1.00 minimum per order</span>
|
|||
|
|
(<a href="https://www.interactivebrokers.com/en/pricing/commissions-options.php" target="_blank" rel="noopener">IBKR docs</a>).
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<div class="row g-3">
|
|||
|
|
<div class="col-12">
|
|||
|
|
<label class="form-label small text-secondary">Plan</label>
|
|||
|
|
<div class="btn-group" role="group" aria-label="Commission plan preset">
|
|||
|
|
<button class="btn btn-sm" :class="c.plan === 'ibkr-fixed' ? 'btn-primary' : 'btn-outline-secondary'" @click="setPlan('ibkr-fixed')">IBKR Fixed / Lite</button>
|
|||
|
|
<button class="btn btn-sm" :class="c.plan === 'ibkr-tiered' ? 'btn-primary' : 'btn-outline-secondary'" @click="setPlan('ibkr-tiered')">IBKR Tiered</button>
|
|||
|
|
<button class="btn btn-sm" :class="c.plan === 'custom' ? 'btn-primary' : 'btn-outline-secondary'" @click="setPlan('custom')">Custom</button>
|
|||
|
|
</div>
|
|||
|
|
<div class="text-secondary small mt-2" x-show="c.plan === 'ibkr-tiered'">
|
|||
|
|
IBKR Tiered: ~$0.15–$0.65 per contract by volume, plus exchange / regulatory fees. Estimated effective ~$0.55/ct, $1.00 min.
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<label class="form-label small text-secondary" for="cm-pc">$ per contract</label>
|
|||
|
|
<input id="cm-pc" type="number" min="0" step="0.01" class="form-control" :value="c.perContract" @change="update('perContract', +$event.target.value || 0)" />
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<label class="form-label small text-secondary" for="cm-min">$ min per order</label>
|
|||
|
|
<input id="cm-min" type="number" min="0" step="0.01" class="form-control" :value="c.perOrderMin" @change="update('perOrderMin', +$event.target.value || 0)" />
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<label class="form-label small text-secondary" for="cm-max">$ max per order <span class="text-secondary">(0 = none)</span></label>
|
|||
|
|
<input id="cm-max" type="number" min="0" step="0.01" class="form-control" :value="c.perOrderMax" @change="update('perOrderMax', +$event.target.value || 0)" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="col-12">
|
|||
|
|
<div class="form-check form-switch">
|
|||
|
|
<input id="cm-leg" type="checkbox" class="form-check-input" :checked="c.applyPerLeg" @change="update('applyPerLeg', $event.target.checked)" />
|
|||
|
|
<label class="form-check-label small" for="cm-leg">Charge each leg as a separate order
|
|||
|
|
<span class="text-secondary">— off (default): multi-leg complex orders count as one, so the per-order minimum applies once.</span>
|
|||
|
|
</label>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<hr class="my-4" style="border-color:#2d3045;">
|
|||
|
|
|
|||
|
|
<h4 class="text-secondary text-uppercase small mb-2" style="letter-spacing:.05em;">Preview</h4>
|
|||
|
|
<div class="row g-3">
|
|||
|
|
<div class="col-md-4"><div class="p-3" style="background:#1e2030; border:1px solid #2d3045; border-radius:.5rem;">
|
|||
|
|
<div class="text-secondary small">1 single-leg, 1 contract</div>
|
|||
|
|
<div class="mono fs-5">Round-trip: <span x-text="'$' + preview([{qty:1}]).toFixed(2)"></span></div>
|
|||
|
|
</div></div>
|
|||
|
|
<div class="col-md-4"><div class="p-3" style="background:#1e2030; border:1px solid #2d3045; border-radius:.5rem;">
|
|||
|
|
<div class="text-secondary small">2-leg vertical, 1 contract each</div>
|
|||
|
|
<div class="mono fs-5">Round-trip: <span x-text="'$' + preview([{qty:1},{qty:1}]).toFixed(2)"></span></div>
|
|||
|
|
</div></div>
|
|||
|
|
<div class="col-md-4"><div class="p-3" style="background:#1e2030; border:1px solid #2d3045; border-radius:.5rem;">
|
|||
|
|
<div class="text-secondary small">4-leg iron condor, 1 contract each</div>
|
|||
|
|
<div class="mono fs-5">Round-trip: <span x-text="'$' + preview([{qty:1},{qty:1},{qty:1},{qty:1}]).toFixed(2)"></span></div>
|
|||
|
|
</div></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="mt-4 d-flex justify-content-between align-items-center">
|
|||
|
|
<button class="btn btn-outline-danger btn-sm" @click="resetDefaults()">Reset to IBKR Fixed defaults</button>
|
|||
|
|
<span class="text-secondary small" x-show="savedFlash" x-cloak x-text="savedFlash"></span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script src="/assets/tabler.min.js" defer></script>
|
|||
|
|
<script src="/assets/settings-store.js"></script>
|
|||
|
|
<script src="/assets/alpine.min.js" defer></script>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
function settingsApp() {
|
|||
|
|
return {
|
|||
|
|
c: { plan:'ibkr-fixed', perContract:0.65, perOrderMin:1.00, perOrderMax:0, applyPerLeg:false },
|
|||
|
|
savedFlash: '',
|
|||
|
|
|
|||
|
|
init() { this.c = SettingsStore.load().commission; },
|
|||
|
|
|
|||
|
|
update(key, val) {
|
|||
|
|
this.c[key] = val;
|
|||
|
|
// changing numeric fields manually -> mark as custom
|
|||
|
|
if (['perContract','perOrderMin','perOrderMax','applyPerLeg'].includes(key)) this.c.plan = 'custom';
|
|||
|
|
this._save();
|
|||
|
|
},
|
|||
|
|
setPlan(plan) {
|
|||
|
|
this.c.plan = plan;
|
|||
|
|
if (plan === 'ibkr-fixed') { this.c.perContract = 0.65; this.c.perOrderMin = 1.00; this.c.perOrderMax = 0; this.c.applyPerLeg = false; }
|
|||
|
|
if (plan === 'ibkr-tiered') { this.c.perContract = 0.55; this.c.perOrderMin = 1.00; this.c.perOrderMax = 0; this.c.applyPerLeg = false; }
|
|||
|
|
this._save();
|
|||
|
|
},
|
|||
|
|
resetDefaults() {
|
|||
|
|
this.c = SettingsStore.reset().commission;
|
|||
|
|
this._save(true);
|
|||
|
|
},
|
|||
|
|
_save(silent) {
|
|||
|
|
SettingsStore.save({ commission: this.c });
|
|||
|
|
if (!silent) {
|
|||
|
|
this.savedFlash = 'Saved · ' + new Date().toLocaleTimeString();
|
|||
|
|
clearTimeout(this._t); this._t = setTimeout(() => { this.savedFlash = ''; }, 1500);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
preview(legs) { return SettingsStore.estimate(legs).roundTrip; },
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|