Show DTE per leg + per-expiry remaining DTE for multi-expiry strategies
- Legs table: small DTE chip next to each leg's expiry (e.g. "14d", "<1d", "exp" — absolute days from today) - Chart header: when active legs span multiple expiries (calendar/diagonal), a "Remaining: 2026-05-15 (0d) · 2026-06-20 (36d)" line shows how many days each unique expiry has left at the current slider position Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -109,11 +109,12 @@
|
|||||||
<button class="btn btn-outline-secondary" @click="zoomFit()" title="Reset pan & zoom">Fit</button>
|
<button class="btn btn-outline-secondary" @click="zoomFit()" title="Reset pan & zoom">Fit</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- time slider -->
|
<!-- time slider -->
|
||||||
<div class="d-flex align-items-center gap-2" style="min-width:300px;">
|
<div class="d-flex align-items-center flex-wrap gap-2" style="min-width:300px;">
|
||||||
<span class="text-secondary small text-nowrap">Now</span>
|
<span class="text-secondary small text-nowrap">Now</span>
|
||||||
<input type="range" class="form-range" min="0" :max="maxDTE" step="1" x-model.number="dteOffset" @input="scheduleRender()" style="min-width:150px;">
|
<input type="range" class="form-range" min="0" :max="maxDTE" step="1" x-model.number="dteOffset" @input="scheduleRender()" style="min-width:150px;">
|
||||||
<span class="text-secondary small text-nowrap">Exp</span>
|
<span class="text-secondary small text-nowrap">Exp</span>
|
||||||
<span class="badge bg-blue-lt text-nowrap" x-text="dteLabel"></span>
|
<span class="badge bg-blue-lt text-nowrap" x-text="dteLabel"></span>
|
||||||
|
<small class="text-secondary w-100" x-show="hasMultiExpiry" x-text="'Remaining: ' + expiryBreakdown"></small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -173,11 +174,14 @@
|
|||||||
</select>
|
</select>
|
||||||
<span x-show="!hasStrikeOpts(lv)" x-text="lv.strike"></span>
|
<span x-show="!hasStrikeOpts(lv)" x-text="lv.strike"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="mono small" style="width:8.5rem">
|
<td class="mono small" style="width:11rem">
|
||||||
<select x-show="hasExpiryOpts(lv)" class="form-select form-select-sm" :value="lv.expiry" @change="changeExpiry(lv.id, $event.target.value)" title="Change expiry — strike, entry, IV & mark update from the new chain">
|
<div class="d-flex align-items-center gap-1 flex-nowrap">
|
||||||
<template x-for="e in expiryOpts(lv)" :key="e"><option :value="e" x-text="e"></option></template>
|
<select x-show="hasExpiryOpts(lv)" class="form-select form-select-sm" :value="lv.expiry" @change="changeExpiry(lv.id, $event.target.value)" title="Change expiry — strike, entry, IV & mark update from the new chain">
|
||||||
</select>
|
<template x-for="e in expiryOpts(lv)" :key="e"><option :value="e" x-text="e"></option></template>
|
||||||
<span x-show="!hasExpiryOpts(lv)" x-text="lv.expiry"></span>
|
</select>
|
||||||
|
<span x-show="!hasExpiryOpts(lv)" x-text="lv.expiry"></span>
|
||||||
|
<span class="badge bg-secondary-lt text-secondary" :title="'Days to expiry from today'" x-text="legDTEStr(lv)"></span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:8.5rem">
|
<td style="width:8.5rem">
|
||||||
<div class="input-group input-group-sm flex-nowrap">
|
<div class="input-group input-group-sm flex-nowrap">
|
||||||
@@ -493,6 +497,22 @@
|
|||||||
if (this.dteOffset === 0) return 'Today (' + ds + ')';
|
if (this.dteOffset === 0) return 'Today (' + ds + ')';
|
||||||
return 'T+' + this.dteOffset + 'd · ' + ds;
|
return 'T+' + this.dteOffset + 'd · ' + ds;
|
||||||
},
|
},
|
||||||
|
get hasMultiExpiry() {
|
||||||
|
return new Set(this.activeLegs.map(l => l.expiry)).size > 1;
|
||||||
|
},
|
||||||
|
get expiryBreakdown() {
|
||||||
|
const uniq = [...new Set(this.activeLegs.map(l => l.expiry))].sort();
|
||||||
|
return uniq.map(e => {
|
||||||
|
const rem = Math.max(0, Math.round(legDTE({expiry:e}) - this.dteOffset));
|
||||||
|
return e + ' (' + rem + 'd)';
|
||||||
|
}).join(' · ');
|
||||||
|
},
|
||||||
|
legDTEStr(lv) {
|
||||||
|
const d = legDTE(lv);
|
||||||
|
if (d < 0) return 'exp';
|
||||||
|
if (d < 1) return '<1d';
|
||||||
|
return Math.round(d) + 'd';
|
||||||
|
},
|
||||||
|
|
||||||
get legsView() {
|
get legsView() {
|
||||||
return this.legs.map(l => {
|
return this.legs.map(l => {
|
||||||
|
|||||||
Reference in New Issue
Block a user