marketmyna 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- marketmyna/__init__.py +14 -0
- marketmyna/agent/__init__.py +8 -0
- marketmyna/agent/agents.py +543 -0
- marketmyna/agent/context.py +69 -0
- marketmyna/agent/dashboard.py +55 -0
- marketmyna/agent/orchestrator.py +153 -0
- marketmyna/agent/sentiment.py +150 -0
- marketmyna/agent/skills.py +119 -0
- marketmyna/ai/__init__.py +1 -0
- marketmyna/ai/portfolio_optimizer.py +330 -0
- marketmyna/analysis/__init__.py +6 -0
- marketmyna/analysis/fundamental.py +329 -0
- marketmyna/analysis/sip_optimizer.py +81 -0
- marketmyna/analysis/technical.py +321 -0
- marketmyna/api/__init__.py +1 -0
- marketmyna/api/app.py +209 -0
- marketmyna/api/deps.py +63 -0
- marketmyna/api/middlewares/__init__.py +0 -0
- marketmyna/api/middlewares/auth.py +116 -0
- marketmyna/api/middlewares/csrf.py +66 -0
- marketmyna/api/middlewares/error_handler.py +38 -0
- marketmyna/api/middlewares/slashes.py +27 -0
- marketmyna/api/v1/__init__.py +0 -0
- marketmyna/api/v1/endpoints/__init__.py +0 -0
- marketmyna/api/v1/endpoints/account.py +166 -0
- marketmyna/api/v1/endpoints/agent.py +114 -0
- marketmyna/api/v1/endpoints/bot.py +38 -0
- marketmyna/api/v1/endpoints/calendar.py +269 -0
- marketmyna/api/v1/endpoints/data_sources.py +174 -0
- marketmyna/api/v1/endpoints/health.py +10 -0
- marketmyna/api/v1/endpoints/listings.py +564 -0
- marketmyna/api/v1/endpoints/macro.py +163 -0
- marketmyna/api/v1/endpoints/portfolio.py +530 -0
- marketmyna/api/v1/endpoints/push.py +119 -0
- marketmyna/api/v1/endpoints/reports.py +49 -0
- marketmyna/api/v1/endpoints/scheduler.py +219 -0
- marketmyna/api/v1/endpoints/stocks.py +400 -0
- marketmyna/api/v1/endpoints/system_config.py +157 -0
- marketmyna/api/v1/endpoints/thesis.py +112 -0
- marketmyna/api/v1/endpoints/trade.py +709 -0
- marketmyna/api/v1/endpoints/updates.py +394 -0
- marketmyna/api/v1/endpoints/watchlists.py +179 -0
- marketmyna/api/v1/router.py +43 -0
- marketmyna/bot/__init__.py +14 -0
- marketmyna/bot/commands/__init__.py +0 -0
- marketmyna/bot/commands/analyze.py +40 -0
- marketmyna/bot/commands/ask.py +51 -0
- marketmyna/bot/commands/base.py +35 -0
- marketmyna/bot/commands/batch.py +53 -0
- marketmyna/bot/commands/common.py +84 -0
- marketmyna/bot/commands/help.py +43 -0
- marketmyna/bot/commands/markets.py +153 -0
- marketmyna/bot/commands/portfolio.py +145 -0
- marketmyna/bot/commands/research.py +323 -0
- marketmyna/bot/commands/status.py +48 -0
- marketmyna/bot/commands/trade.py +176 -0
- marketmyna/bot/dispatcher.py +95 -0
- marketmyna/bot/formatting.py +25 -0
- marketmyna/bot/models.py +27 -0
- marketmyna/bot/registry.py +50 -0
- marketmyna/bot/telegram_listener.py +227 -0
- marketmyna/cli/__init__.py +1 -0
- marketmyna/cli/scheduled_run.py +292 -0
- marketmyna/core/__init__.py +6 -0
- marketmyna/core/compliance.py +53 -0
- marketmyna/core/config.py +377 -0
- marketmyna/core/constants.py +69 -0
- marketmyna/core/home.py +22 -0
- marketmyna/core/numbers.py +28 -0
- marketmyna/core/secret_store.py +104 -0
- marketmyna/core/tenant.py +130 -0
- marketmyna/data/__init__.py +8 -0
- marketmyna/data/base.py +36 -0
- marketmyna/data/categories.py +272 -0
- marketmyna/data/china.py +360 -0
- marketmyna/data/crypto.py +200 -0
- marketmyna/data/ecb_fx.py +131 -0
- marketmyna/data/extra_sources.py +569 -0
- marketmyna/data/india.py +241 -0
- marketmyna/data/india_filings.py +343 -0
- marketmyna/data/listings.py +1314 -0
- marketmyna/data/mutual_funds.py +34 -0
- marketmyna/data/news.py +98 -0
- marketmyna/data/news_search.py +346 -0
- marketmyna/data/nse_deals.py +138 -0
- marketmyna/data/resilience.py +173 -0
- marketmyna/data/sec_facts.py +252 -0
- marketmyna/data/shariah.py +283 -0
- marketmyna/data/social/__init__.py +9 -0
- marketmyna/data/social/base.py +100 -0
- marketmyna/data/social/browser.py +92 -0
- marketmyna/data/social/hackernews.py +53 -0
- marketmyna/data/social/reddit.py +397 -0
- marketmyna/data/social/stocktwits.py +63 -0
- marketmyna/data/social/valuepickr.py +53 -0
- marketmyna/data/stocks.py +197 -0
- marketmyna/data/yahoo_price.py +48 -0
- marketmyna/launcher.py +71 -0
- marketmyna/llm/__init__.py +33 -0
- marketmyna/llm/backend_factory.py +51 -0
- marketmyna/llm/backend_registry.py +19 -0
- marketmyna/llm/channels.py +447 -0
- marketmyna/llm/json_reply.py +63 -0
- marketmyna/llm/litellm_backend.py +197 -0
- marketmyna/llm/model_catalog.py +166 -0
- marketmyna/llm/model_health.py +193 -0
- marketmyna/llm/protocol.py +111 -0
- marketmyna/llm/providers.py +128 -0
- marketmyna/llm/store.py +128 -0
- marketmyna/notifiers/__init__.py +35 -0
- marketmyna/notifiers/apprise_sender.py +43 -0
- marketmyna/notifiers/astrbot.py +47 -0
- marketmyna/notifiers/bark.py +24 -0
- marketmyna/notifiers/base.py +80 -0
- marketmyna/notifiers/dingtalk.py +54 -0
- marketmyna/notifiers/discord.py +39 -0
- marketmyna/notifiers/dispatcher.py +153 -0
- marketmyna/notifiers/email.py +99 -0
- marketmyna/notifiers/feishu.py +57 -0
- marketmyna/notifiers/googlechat.py +24 -0
- marketmyna/notifiers/gotify.py +36 -0
- marketmyna/notifiers/matrix.py +28 -0
- marketmyna/notifiers/ntfy.py +36 -0
- marketmyna/notifiers/pushbullet.py +24 -0
- marketmyna/notifiers/pushover.py +41 -0
- marketmyna/notifiers/pushplus.py +41 -0
- marketmyna/notifiers/serverchan3.py +40 -0
- marketmyna/notifiers/settings_schema.py +119 -0
- marketmyna/notifiers/signal_messenger.py +25 -0
- marketmyna/notifiers/slack.py +36 -0
- marketmyna/notifiers/teams.py +37 -0
- marketmyna/notifiers/telegram.py +81 -0
- marketmyna/notifiers/twilio.py +33 -0
- marketmyna/notifiers/webhook.py +44 -0
- marketmyna/notifiers/webpush.py +222 -0
- marketmyna/notifiers/wechat.py +40 -0
- marketmyna/notifiers/whatsapp.py +27 -0
- marketmyna/portfolio/__init__.py +6 -0
- marketmyna/portfolio/analytics.py +336 -0
- marketmyna/portfolio/manager.py +383 -0
- marketmyna/portfolio/models.py +155 -0
- marketmyna/portfolio/optimizers.py +88 -0
- marketmyna/portfolio/review.py +411 -0
- marketmyna/services/__init__.py +1 -0
- marketmyna/services/accounts.py +278 -0
- marketmyna/services/ai_access.py +94 -0
- marketmyna/services/analysis_run.py +491 -0
- marketmyna/services/big_trades.py +335 -0
- marketmyna/services/brokers/__init__.py +0 -0
- marketmyna/services/brokers/angel.py +271 -0
- marketmyna/services/brokers/finnhub.py +209 -0
- marketmyna/services/byok_detect.py +196 -0
- marketmyna/services/calendar.py +748 -0
- marketmyna/services/central_banks.py +202 -0
- marketmyna/services/commodities.py +134 -0
- marketmyna/services/compare.py +307 -0
- marketmyna/services/cot.py +148 -0
- marketmyna/services/country_macro.py +135 -0
- marketmyna/services/crude_sensitivity.py +239 -0
- marketmyna/services/crypto_mood.py +135 -0
- marketmyna/services/crypto_screens.py +226 -0
- marketmyna/services/data_export.py +91 -0
- marketmyna/services/dcf.py +220 -0
- marketmyna/services/dcf_model.py +194 -0
- marketmyna/services/delivery.py +142 -0
- marketmyna/services/discovery.py +146 -0
- marketmyna/services/dividends.py +95 -0
- marketmyna/services/earnings.py +305 -0
- marketmyna/services/econ_calendar.py +495 -0
- marketmyna/services/eia_stocks.py +115 -0
- marketmyna/services/estimates.py +109 -0
- marketmyna/services/etf.py +236 -0
- marketmyna/services/etf_rotation.py +193 -0
- marketmyna/services/etf_screens.py +196 -0
- marketmyna/services/financials.py +639 -0
- marketmyna/services/fund_ai.py +181 -0
- marketmyna/services/fund_analytics.py +371 -0
- marketmyna/services/fund_cost.py +147 -0
- marketmyna/services/fund_holdings.py +664 -0
- marketmyna/services/fund_peers.py +247 -0
- marketmyna/services/fund_rotation.py +206 -0
- marketmyna/services/fund_style.py +179 -0
- marketmyna/services/funds.py +70 -0
- marketmyna/services/hot_stocks.py +358 -0
- marketmyna/services/india_flows.py +263 -0
- marketmyna/services/india_rates.py +258 -0
- marketmyna/services/investor_lenses.py +271 -0
- marketmyna/services/leadership.py +165 -0
- marketmyna/services/live_market.py +497 -0
- marketmyna/services/live_quotes.py +295 -0
- marketmyna/services/macro.py +182 -0
- marketmyna/services/market_calendar.py +399 -0
- marketmyna/services/market_mood.py +168 -0
- marketmyna/services/market_valuation.py +231 -0
- marketmyna/services/mf_holdings.py +199 -0
- marketmyna/services/mf_insights.py +132 -0
- marketmyna/services/mf_lumpsum.py +587 -0
- marketmyna/services/mf_portfolio_ai.py +195 -0
- marketmyna/services/nse_events.py +98 -0
- marketmyna/services/overview.py +366 -0
- marketmyna/services/ownership.py +143 -0
- marketmyna/services/quality_scores.py +199 -0
- marketmyna/services/rates.py +335 -0
- marketmyna/services/reconcile.py +343 -0
- marketmyna/services/report.py +584 -0
- marketmyna/services/report_i18n.py +678 -0
- marketmyna/services/rotation.py +224 -0
- marketmyna/services/runtime_scheduler.py +548 -0
- marketmyna/services/schedule_config.py +251 -0
- marketmyna/services/schedule_time.py +39 -0
- marketmyna/services/screens.py +398 -0
- marketmyna/services/sec_mdna.py +173 -0
- marketmyna/services/shariah.py +246 -0
- marketmyna/services/sip.py +148 -0
- marketmyna/services/sip_days.py +362 -0
- marketmyna/services/smart_file.py +595 -0
- marketmyna/services/smart_pdf.py +425 -0
- marketmyna/services/smart_report.py +370 -0
- marketmyna/services/social_sentiment.py +511 -0
- marketmyna/services/thesis.py +328 -0
- marketmyna/services/translate.py +146 -0
- marketmyna/services/valuation.py +173 -0
- marketmyna/services/worker_pool.py +149 -0
- marketmyna/services/world_markets.py +208 -0
- marketmyna/storage.py +722 -0
- marketmyna/strategies/README.md +51 -0
- marketmyna/strategies/bottom_volume.yaml +49 -0
- marketmyna/strategies/box_oscillation.yaml +69 -0
- marketmyna/strategies/bull_trend.yaml +49 -0
- marketmyna/strategies/chan_theory.yaml +58 -0
- marketmyna/strategies/dragon_head.yaml +44 -0
- marketmyna/strategies/emotion_cycle.yaml +79 -0
- marketmyna/strategies/event_driven.yaml +54 -0
- marketmyna/strategies/expectation_repricing.yaml +54 -0
- marketmyna/strategies/growth_quality.yaml +54 -0
- marketmyna/strategies/hot_theme.yaml +54 -0
- marketmyna/strategies/ma_golden_cross.yaml +46 -0
- marketmyna/strategies/one_yang_three_yin.yaml +37 -0
- marketmyna/strategies/shrink_pullback.yaml +46 -0
- marketmyna/strategies/volume_breakout.yaml +47 -0
- marketmyna/strategies/wave_theory.yaml +64 -0
- marketmyna/trading/__init__.py +2 -0
- marketmyna/trading/alerts.py +356 -0
- marketmyna/trading/backtest.py +317 -0
- marketmyna/trading/charges.py +82 -0
- marketmyna/trading/chart.py +197 -0
- marketmyna/trading/indicators.py +303 -0
- marketmyna/trading/journal.py +74 -0
- marketmyna/trading/knn.py +164 -0
- marketmyna/trading/lots.py +109 -0
- marketmyna/trading/market_hours.py +66 -0
- marketmyna/trading/options.py +554 -0
- marketmyna/trading/pairs.py +94 -0
- marketmyna/trading/risk.py +170 -0
- marketmyna/trading/scanner.py +500 -0
- marketmyna/trading/volatility.py +163 -0
- marketmyna/utils/__init__.py +1 -0
- marketmyna/utils/deadline.py +36 -0
- marketmyna/utils/log_redact.py +52 -0
- marketmyna/utils/yahoo_gate.py +183 -0
- marketmyna/utils/yf_lock.py +12 -0
- marketmyna/web/apple-touch-icon.png +0 -0
- marketmyna/web/assets/Account-CA9NFDKO.js +1 -0
- marketmyna/web/assets/Analyze-uM0srB_U.js +7 -0
- marketmyna/web/assets/AreaChart-2i67V6Jf.js +1 -0
- marketmyna/web/assets/BarChart-_yngarVl.js +3 -0
- marketmyna/web/assets/Bot-E4gpf1qZ.js +1 -0
- marketmyna/web/assets/CandleChart-CioqTqMV.js +1 -0
- marketmyna/web/assets/Compare-D6_2CPl4.js +1 -0
- marketmyna/web/assets/ExportMenu-DaZ1xVmW.js +1 -0
- marketmyna/web/assets/LineChart-BaOkD1Ta.js +57 -0
- marketmyna/web/assets/Markets-BMw_M1sJ.js +1 -0
- marketmyna/web/assets/Portfolio-DQEdHVc2.js +1 -0
- marketmyna/web/assets/ReportView-BzhdcqSh.js +1 -0
- marketmyna/web/assets/Scheduler-I9PDKxTd.js +1 -0
- marketmyna/web/assets/Settings-DpXfHolW.js +3 -0
- marketmyna/web/assets/SipDays-C9q3bNSx.js +1 -0
- marketmyna/web/assets/SymbolSearch-CBOVPEk1.js +1 -0
- marketmyna/web/assets/Trade-_CM7HC4H.js +2 -0
- marketmyna/web/assets/TradeChart-ZjsycacC.js +1 -0
- marketmyna/web/assets/WatchButton-ComYW56_.js +1 -0
- marketmyna/web/assets/Watchlist-DAjLb0jd.js +1 -0
- marketmyna/web/assets/app-BP1o7WZS.js +1 -0
- marketmyna/web/assets/app-BkIUKdld.js +1 -0
- marketmyna/web/assets/app-CKeSYhEt.js +1 -0
- marketmyna/web/assets/app-CN1OERYX.js +1 -0
- marketmyna/web/assets/app-DIQllha5.js +1 -0
- marketmyna/web/assets/app-DeiAW0tX.js +1 -0
- marketmyna/web/assets/br-Cu5YU29T.svg +45 -0
- marketmyna/web/assets/browser-CR-ks2Fp.js +19 -0
- marketmyna/web/assets/browser-D5K_K_gj.js +1 -0
- marketmyna/web/assets/common-0wvpAVpd.js +1 -0
- marketmyna/web/assets/common-3ghy53Us.js +1 -0
- marketmyna/web/assets/common-Bib2unjX.js +1 -0
- marketmyna/web/assets/common-BvSJP0w_.js +1 -0
- marketmyna/web/assets/common-CSfyC0Sp.js +1 -0
- marketmyna/web/assets/common-C_t-iZPf.js +1 -0
- marketmyna/web/assets/compare-DMcsx70H.js +1 -0
- marketmyna/web/assets/es-d5m8M5h8.svg +544 -0
- marketmyna/web/assets/exporter-DiMg2O5d.js +3 -0
- marketmyna/web/assets/files-CpgiZRbN.js +1 -0
- marketmyna/web/assets/format-d8InM0Zw.js +9 -0
- marketmyna/web/assets/html2canvas-Bw0OShmD.js +5 -0
- marketmyna/web/assets/index-CKAnq-Or.js +12 -0
- marketmyna/web/assets/index-D4U8E6LH.css +2 -0
- marketmyna/web/assets/index.es-iBEw7jOv.js +5 -0
- marketmyna/web/assets/ir-cCIgaNf6.svg +219 -0
- marketmyna/web/assets/jspdf.es.min-C4285IdL.js +79 -0
- marketmyna/web/assets/jspdf.plugin.autotable-2eOJeXl-.js +2 -0
- marketmyna/web/assets/lightweight-charts.production-BF2noug5.js +1 -0
- marketmyna/web/assets/listings-BefgXpb1.js +1 -0
- marketmyna/web/assets/liveQuotes-CtSmCUFA.js +1 -0
- marketmyna/web/assets/markets-BI4AhI9W.js +1 -0
- marketmyna/web/assets/markets-BUHUdYpT.js +1 -0
- marketmyna/web/assets/markets-BqvN1Bvf.js +1 -0
- marketmyna/web/assets/markets-DPO40TTe.js +1 -0
- marketmyna/web/assets/markets-bsiPo-Tk.js +1 -0
- marketmyna/web/assets/markets-ff1e792u.js +1 -0
- marketmyna/web/assets/montecarlo-BsNlH2qe.js +1 -0
- marketmyna/web/assets/options-BYAZnwzW.js +1 -0
- marketmyna/web/assets/preload-helper-BLdHbfdN.js +1 -0
- marketmyna/web/assets/purify.es-Dqk5qvad.js +3 -0
- marketmyna/web/assets/rolldown-runtime-XKyaHtl9.js +1 -0
- marketmyna/web/assets/sa-Dh79zbT9.svg +25 -0
- marketmyna/web/assets/toast-DDradTZw.js +1 -0
- marketmyna/web/assets/trade-fndw1Ql3.js +1 -0
- marketmyna/web/assets/ui-gsFb8B2m.js +1 -0
- marketmyna/web/assets/watchlists-B6YqwUIk.js +1 -0
- marketmyna/web/brand/logo-mark.webp +0 -0
- marketmyna/web/favicon.png +0 -0
- marketmyna/web/icon-192.png +0 -0
- marketmyna/web/icon-512.png +0 -0
- marketmyna/web/index.html +34 -0
- marketmyna/web/manifest.webmanifest +28 -0
- marketmyna/web/robots.txt +2 -0
- marketmyna/web/sw.js +40 -0
- marketmyna/web/theme-init.js +37 -0
- marketmyna-0.2.0.dist-info/METADATA +345 -0
- marketmyna-0.2.0.dist-info/RECORD +344 -0
- marketmyna-0.2.0.dist-info/WHEEL +5 -0
- marketmyna-0.2.0.dist-info/entry_points.txt +2 -0
- marketmyna-0.2.0.dist-info/licenses/LICENSE +202 -0
- marketmyna-0.2.0.dist-info/licenses/NOTICE +22 -0
- marketmyna-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,l as n,n as r,p as i,u as a}from"./format-d8InM0Zw.js";import{t as o}from"./toast-DDradTZw.js";import{C as s,D as c,S as l,_ as u,a as d,c as f,f as p,g as m,i as h,l as g,n as _,o as v,p as y,r as b,t as x,w as S,y as C}from"./ui-gsFb8B2m.js";import{O as w,d as T,f as E,g as D,h as O,l as k,m as A,n as ee,p as j,t as M,u as N}from"./index-CKAnq-Or.js";import{S as P}from"./listings-BefgXpb1.js";import{n as F,r as te}from"./options-BYAZnwzW.js";import{t as I}from"./SymbolSearch-CBOVPEk1.js";var L=e(t(),1),R=i(),z={telegram:`Telegram`,discord:`Discord`,slack:`Slack`,email:`Email`,dingtalk:`DingTalk`,feishu:`Feishu`,wechat:`WeChat`,pushover:`Pushover`,ntfy:`ntfy`,gotify:`Gotify`,pushplus:`PushPlus`,serverchan3:`ServerChan3`,astrbot:`AstrBot`,webhook:`Webhook`,webpush:`Browser push`,whatsapp:`WhatsApp`,twilio:`Twilio SMS`,teams:`Teams`,googlechat:`Google Chat`,matrix:`Matrix`,signal:`Signal`,bark:`Bark`,pushbullet:`Pushbullet`,apprise:`Apprise`},B=[{id:`email`,label:`Email`},{id:`telegram`,label:`Telegram`}],V=new Set([`market`,`calls`,`portfolio`,`alerts`,`hot_trade`,`hot_invest`,`funds`]);function ne({draft:e,options:t,onChange:n,footer:r}){let i=ee(),[a,o]=(0,L.useState)(null),[l,m]=(0,L.useState)(``),[_,y]=(0,L.useState)({}),S=e.mfCodes.filter(e=>!(e in _)).join(`,`);if((0,L.useEffect)(()=>{if(!S)return;let e=!1;for(let t of S.split(`,`))P(t,`india`,`mf`,1).then(n=>{let r=n.find(e=>e.symbol===t);e||y(e=>({...e,[t]:r?.name??`Scheme ${t}`}))}).catch(()=>{});return()=>{e=!0}},[S]),!t)return(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Report content & delivery`,icon:`bell`}),(0,R.jsx)(d,{children:(0,R.jsx)(C,{className:`h-40 w-full`})})]});let w=t.languages.map(e=>({value:e.code,label:`${e.native}${e.native===e.english?``:` · ${e.english}`}${e.builtin?``:` (AI)`}`})),T=t.languages.find(t=>t.code===e.reportLanguage),E=t.sections.filter(e=>M(i,e.area??void 0)),D=new Set(E.map(e=>e.id)),O=e.reportSections.filter(e=>!D.has(e)&&t.sections.some(t=>t.id===e)),k=D.has(`funds`),A=E.filter(e=>!V.has(e.id));function j(e){return t.sections.map(e=>e.id).filter(t=>e.includes(t))}function N(e,t){return j(e.includes(t)?e.filter(e=>e!==t):[...e,t])}function F(t,r){let i={...e.stockSections};r===null?delete i[t]:i[t]=r,n({stockSections:i})}return(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Report content & delivery`,description:`Choose what each report contains and the language every channel receives.`,icon:`bell`}),(0,R.jsxs)(d,{className:`space-y-7`,children:[!t.llm_configured&&(0,R.jsx)(x,{tone:`accent`,title:`No AI model configured`,children:`Reports still arrive with prices, technical, risk, fundamentals and news, and labels in the built-in languages. The AI view (a bullish / neutral / bearish outlook with its reasoning), AI-only languages and translation of free text such as headlines need an AI model under Settings.`}),(0,R.jsxs)(`section`,{className:`grid gap-6 md:grid-cols-2`,children:[(0,R.jsx)(f,{label:`Report language`,hint:T&&!T.builtin?`Translated entirely by your AI model.`:`Labels are built in; AI commentary and headlines are translated when an AI model is set.`,children:(0,R.jsx)(u,{options:w,value:e.reportLanguage,onChange:e=>n({reportLanguage:e.target.value})})}),(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`Language per channel`}),t.channels.length===0?(0,R.jsxs)(`p`,{className:`rounded-lg border border-dashed border-line px-3 py-2.5 text-xs text-muted`,children:[`No notification channel configured yet. Add Telegram, email and others under`,` `,(0,R.jsx)(`a`,{href:`/settings`,className:`text-accent-fg hover:underline`,children:`Settings → Notifications`}),`.`]}):(0,R.jsx)(`ul`,{className:`space-y-2`,children:t.channels.map(t=>(0,R.jsxs)(`li`,{className:`grid grid-cols-[110px_minmax(0,1fr)] items-center gap-3`,children:[(0,R.jsx)(`span`,{className:`text-sm`,children:z[t]??t}),(0,R.jsx)(u,{options:[{value:``,label:`Same as report language`},...w],value:e.channelLanguages[t]??``,onChange:r=>{let i={...e.channelLanguages};r.target.value?i[t]=r.target.value:delete i[t],n({channelLanguages:i})}})]},t))})]})]}),(0,R.jsxs)(`section`,{className:c(`rounded-lg border px-4 py-3.5`,e.smartEnabled?`border-accent/60 bg-accent-soft/40`:`border-line`),children:[(0,R.jsx)(s,{checked:e.smartEnabled,onChange:e=>n({smartEnabled:e}),label:`Smart messaging`,description:(0,R.jsxs)(R.Fragment,{children:[`For long watchlists: instead of a block per stock, the message carries only today's top`,` `,e.smartTopN,` stocks in one or two lines each. Every stock (normal range, P/E, 1-week range and a bullish / neutral / bearish reading of its indicators) goes into a full report, sent by email and opened by link. No buy or sell calls, targets or stops.`,e.symbols.length>=30&&!e.smartEnabled&&(0,R.jsxs)(`b`,{className:`text-fg`,children:[` Recommended: each run covers `,e.symbols.length,` stocks.`]})]})}),e.smartEnabled&&(0,R.jsxs)(`div`,{className:`mt-4 space-y-4`,children:[(0,R.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,R.jsx)(f,{label:`Stocks in the message`,hint:`Ranked by today's move, levels hit, RSI extremes and volume.`,children:(0,R.jsx)(u,{options:[3,5,10].map(e=>({value:String(e),label:`Top ${e}`})),value:String(e.smartTopN),onChange:e=>n({smartTopN:Number(e.target.value)})})}),(0,R.jsx)(f,{label:`AI review`,hint:t.llm_configured?`Only the most notable stocks get the AI pipeline, to keep AI cost low.`:`Needs an AI model (Settings). Without one, the bullish / neutral / bearish reading comes from the computed rules.`,children:(0,R.jsx)(u,{options:[{value:`0`,label:`None (computed only)`},...[5,10,20].map(e=>({value:String(e),label:`Top ${e} stocks`}))],value:String(e.smartAiTop),onChange:e=>n({smartAiTop:Number(e.target.value)})})})]}),(0,R.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-[200px_minmax(0,1fr)]`,children:[(0,R.jsx)(f,{label:`Report file`,hint:`The key figures for every stock: market, calls, your portfolio, valuation vs sector, the AI summary, ranges and risk. News and alerts stay in the message.`,children:(0,R.jsx)(u,{options:[{value:`pdf`,label:`PDF (to read)`},{value:`xlsx`,label:`Excel (to sort and filter)`},{value:`none`,label:`No file`}],value:e.smartFile,onChange:e=>n({smartFile:e.target.value})})}),e.smartFile!==`none`&&(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`Send the file to`}),(0,R.jsx)(`div`,{className:`flex flex-wrap gap-4`,children:B.map(t=>(0,R.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:e.smartFileChannels.includes(t.id),onChange:()=>n({smartFileChannels:e.smartFileChannels.includes(t.id)?e.smartFileChannels.filter(e=>e!==t.id):[...e.smartFileChannels,t.id]}),className:`h-4 w-4 accent-[var(--color-accent)]`}),t.label]},t.id))}),(0,R.jsx)(`span`,{className:`mt-1.5 block text-xs text-muted`,children:e.smartFileChannels.length===0?`Pick at least one, or the file is not sent.`:`Email gets it as an attachment, Telegram as a document after the short message. Set the channels up under Settings → Notifications.`})]})]}),(0,R.jsxs)(`label`,{className:`flex cursor-pointer items-start gap-3`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:e.smartEmailFull,onChange:e=>n({smartEmailFull:e.target.checked}),className:`mt-0.5 h-4 w-4 accent-[var(--color-accent)]`}),(0,R.jsxs)(`span`,{children:[(0,R.jsx)(`span`,{className:`block text-sm font-medium`,children:`Email the full table`}),(0,R.jsxs)(`span`,{className:`block text-xs text-muted`,children:[`The email channel gets the short brief plus the full table of every stock.`,!t.channels.includes(`email`)&&` Email is not configured yet (Settings → Notifications).`]})]})]}),(0,R.jsx)(f,{label:`Public address for report links (optional)`,hint:e.reportBaseUrl.trim()&&!/^https?:\/\/\S+$/.test(e.reportBaseUrl.trim())?(0,R.jsx)(`span`,{className:`text-down`,children:`Start with http:// or https://`}):`Where your phone can open MarketMyna, e.g. a Tailscale or domain address. Messages then end with a link to the full report. Leave empty to rely on email and the Scheduler page.`,children:(0,R.jsx)(p,{value:e.reportBaseUrl,onChange:e=>n({reportBaseUrl:e.target.value}),placeholder:typeof window<`u`?window.location.origin:`https://marketmyna.example.ts.net`})})]})]}),(0,R.jsxs)(`section`,{className:c(e.smartEnabled&&`opacity-60`),children:[(0,R.jsxs)(`div`,{className:`mb-2 flex flex-wrap items-baseline justify-between gap-2`,children:[(0,R.jsx)(`span`,{className:`text-xs font-medium text-muted`,children:`Sections in every report`}),(0,R.jsxs)(`div`,{className:`flex gap-3 text-xs`,children:[(0,R.jsx)(`button`,{type:`button`,className:`text-muted hover:text-fg`,onClick:()=>n({reportSections:j([...O,...E.map(e=>e.id)])}),children:`Select all`}),(0,R.jsx)(`button`,{type:`button`,className:`text-muted hover:text-fg`,onClick:()=>n({reportSections:j([...O,...E.filter(e=>e.default).map(e=>e.id)])}),children:`Defaults`})]})]}),(0,R.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2 lg:grid-cols-3`,children:E.map(t=>{let r=e.reportSections.includes(t.id);return(0,R.jsxs)(`label`,{className:c(`flex items-start gap-3 rounded-lg border px-3 py-2.5 transition-colors`,`cursor-pointer`,r?`border-accent/60 bg-accent-soft`:`border-line hover:border-line-strong`),children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:r,onChange:()=>n({reportSections:N(e.reportSections,t.id)}),className:`mt-0.5 h-4 w-4 accent-[var(--color-accent)]`}),(0,R.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,R.jsx)(`span`,{className:`flex items-center gap-2 text-sm font-medium`,children:t.label}),(0,R.jsx)(`span`,{className:`block text-xs text-muted`,children:t.description})]})]},t.id)})}),e.smartEnabled&&(0,R.jsx)(`p`,{className:`mt-2 text-xs text-muted`,children:`Smart messaging is on: these sections and the per-stock choices below are used when it is turned off. The report file always carries the same key figures.`}),e.reportSections.length===0&&(0,R.jsx)(`p`,{className:`mt-2 text-xs text-warn`,children:`No sections selected: reports will only list each stock's name.`}),O.length>0&&i&&(0,R.jsxs)(`p`,{className:`mt-2 text-xs text-faint`,children:[`Also in your report from the `,i===`trader`?`Investor`:`Trader`,` area:`,` `,O.map(e=>t.sections.find(t=>t.id===e)?.label??e).join(`, `),`.`,` `,(0,R.jsx)(`button`,{type:`button`,className:`text-accent-fg hover:underline`,onClick:()=>n({reportSections:e.reportSections.filter(e=>D.has(e))}),children:`Remove them`})]})]}),k&&(0,R.jsxs)(`section`,{className:c(!e.reportSections.includes(`funds`)&&`opacity-60`),children:[(0,R.jsx)(`span`,{className:`mb-1 block text-xs font-medium text-muted`,children:`Mutual funds to track`}),(0,R.jsx)(`p`,{className:`mb-3 text-xs text-muted`,children:`NAV, day change and 1-month / 1-year returns for each fund, in every report.`}),(0,R.jsx)(I,{value:l,onChange:m,market:`india`,type:`mf`,placeholder:`Search a fund, e.g. Parag Parikh Flexi Cap Direct Growth`,onSelect:t=>{e.mfCodes.includes(t.symbol)||n({mfCodes:[...e.mfCodes,t.symbol]}),y(e=>({...e,[t.symbol]:t.name})),m(``)}}),e.mfCodes.length>0&&(0,R.jsx)(`ul`,{className:`mt-3 divide-y divide-line rounded-lg border border-line`,children:e.mfCodes.map(t=>(0,R.jsxs)(`li`,{className:`flex items-center gap-3 px-3 py-2 text-sm`,children:[(0,R.jsx)(`span`,{className:`font-mono text-xs text-muted`,children:t}),(0,R.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:_[t]??`Scheme `+t}),(0,R.jsx)(`button`,{type:`button`,onClick:()=>n({mfCodes:e.mfCodes.filter(e=>e!==t)}),className:`rounded-md p-1 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Remove ${t}`,children:(0,R.jsx)(g,{name:`x`})})]},t))})]}),(0,R.jsxs)(`section`,{children:[(0,R.jsx)(`span`,{className:`mb-1 block text-xs font-medium text-muted`,children:`Per-stock sections`}),(0,R.jsxs)(`p`,{className:`mb-3 text-xs text-muted`,children:[`Give a stock its own sections, e.g. `,i===`trader`?`trade levels and indicators for active trades, news for event plays`:`news and fundamentals for long-term holdings, valuation for ones you may add to`,`. Report-wide sections (market overview, movers and AI outlook, portfolio, alerts, hot stocks) always follow the report settings above.`]}),e.symbols.length===0?(0,R.jsx)(`p`,{className:`text-xs text-faint`,children:`Choose what to run above first.`}):(0,R.jsx)(`ul`,{className:`divide-y divide-line rounded-lg border border-line`,children:e.symbols.map(n=>{let r=e.stockSections[n],i=a===n;return(0,R.jsxs)(`li`,{children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3 px-3 py-2`,children:[(0,R.jsx)(`span`,{className:`font-mono text-sm font-medium`,children:n}),(0,R.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-xs text-muted`,children:r?r.length?r.map(e=>t.sections.find(t=>t.id===e)?.label??e).join(`, `):`Name only`:`Uses report sections`}),r&&(0,R.jsx)(`button`,{type:`button`,onClick:()=>F(n,null),className:`text-xs text-muted hover:text-fg`,children:`Reset`}),(0,R.jsxs)(b,{variant:`ghost`,size:`sm`,onClick:()=>{r||F(n,e.reportSections.filter(e=>!V.has(e))),o(i?null:n)},children:[(0,R.jsx)(g,{name:`chevron`,className:c(`h-3.5 w-3.5 transition-transform`,i&&`rotate-90`)}),`Customize`]})]}),i&&r&&(0,R.jsx)(`div`,{className:`flex flex-wrap gap-1.5 border-t border-line bg-canvas/40 px-3 py-3`,children:A.map(e=>{let t=r.includes(e.id);return(0,R.jsx)(`button`,{type:`button`,"aria-pressed":t,onClick:()=>F(n,N(r,e.id)),className:c(`rounded-full border px-3 py-1 text-xs font-medium`,t?`border-accent bg-accent-soft text-fg`:`border-line text-muted hover:text-fg`),children:e.label},e.id)})})]},n)})})]})]}),r]})}var re=[{value:`daily`,label:`Daily at time`},{value:`interval`,label:`Every N minutes`}],ie=[15,30,60,120,240,360];function H(e){return{enabled:e.enabled,cadence:e.interval_minutes?`interval`:`daily`,interval:e.interval_minutes?String(e.interval_minutes):`60`,time:e.time_of_day??`09:30`,symbols:e.symbols,market:e.market,mode:e.mode,reportLanguage:e.report_language??`en`,reportSections:e.report_sections??[],stockSections:e.stock_sections??{},channelLanguages:e.channel_languages??{},mfCodes:e.mf_codes??[],smartEnabled:e.smart_enabled??!1,smartTopN:e.smart_top_n??5,smartAiTop:e.smart_ai_top??10,smartEmailFull:e.smart_email_full??!0,smartFile:e.smart_file??`pdf`,smartFileChannels:e.smart_file_channels??[`email`,`telegram`],reportBaseUrl:e.report_base_url??``,sources:e.sources??[`custom`],watchlistIds:e.watchlist_ids??[],portfolioNames:e.portfolio_names??[]}}function U(e){return{enabled:e.enabled,interval_minutes:e.cadence===`interval`?parseInt(e.interval,10):null,time_of_day:e.cadence===`daily`?e.time:null,symbols:e.symbols,market:e.market,mode:e.mode,report_language:e.reportLanguage,report_sections:e.reportSections,stock_sections:e.stockSections,channel_languages:e.channelLanguages,mf_codes:e.mfCodes,smart_enabled:e.smartEnabled,smart_top_n:e.smartTopN,smart_ai_top:e.smartAiTop,smart_email_full:e.smartEmailFull,smart_file:e.smartFile,smart_file_channels:e.smartFileChannels,report_base_url:e.reportBaseUrl.trim(),sources:e.sources,watchlist_ids:e.watchlistIds,portfolio_names:e.portfolioNames}}function ae(e,t,n){if(!e.enabled)return`Disabled`;if(!t)return`Nothing to run`;if(e.interval_minutes){if(!e.last_run_at)return`On next tick`;let t=a(e.last_run_at).getTime()+e.interval_minutes*6e4;return t<=Date.now()?`On next tick`:new Date(t).toLocaleString()}return e.time_of_day?`Daily at ${e.time_of_day}${n?` (${n.replace(/_/g,` `)})`:``}`:`Not scheduled`}function W(){let e=ee(),[t,i]=(0,L.useState)(null),[l,u]=(0,L.useState)(!1),[_,S]=(0,L.useState)(null),[E,M]=(0,L.useState)(!1),[P,F]=(0,L.useState)(!1),[I,z]=(0,L.useState)(null),[B,V]=(0,L.useState)(null),[W,q]=(0,L.useState)(null),[J,Y]=(0,L.useState)(null),ce=D(e=>e.me?.timezone);async function le(){try{let e=await T();i(e.schedule),u(e.running),S(H(e.schedule)),V(null)}catch(e){V(r(e))}}(0,L.useEffect)(()=>{le(),k().then(q).catch(()=>q(null)),N().then(Y).catch(()=>Y({watchlists:[],portfolios:[]}))},[]);let ue=(0,L.useMemo)(()=>_?j(_,J):[],[_,J]),X=(0,L.useMemo)(()=>t?j(H(t),J):[],[t,J]),Z=(0,L.useMemo)(()=>t!=null&&_!=null&&JSON.stringify(U(_))!==JSON.stringify(U(H(t))),[t,_]),de=_?.cadence!==`interval`||Number(_.interval)>=1&&Number.isInteger(Number(_.interval)),fe=_?.cadence!==`daily`||/^\d{2}:\d{2}$/.test(_.time),pe=!_?.reportBaseUrl.trim()||/^https?:\/\/\S+$/.test(_.reportBaseUrl.trim()),me=(_?.sources.length??0)>0,Q=de&&fe&&pe&&me;function $(e){S(t=>t&&{...t,...e})}async function he(){if(_&&Q){M(!0);try{let e=await O(U(_));i(e),S(H(e)),o.success(`Schedule saved`)}catch(e){o.error(r(e))}finally{M(!1)}}}async function ge(){F(!0),z(null);try{let e=await A();z(e),o[e.status===`ok`?`success`:`info`](`Run finished: ${e.status}`),await le()}catch(e){o.error(r(e))}finally{F(!1)}}return B?(0,R.jsx)(x,{title:`Could not load scheduler`,children:B}):!t||!_?(0,R.jsx)(C,{className:`h-96 w-full`}):(0,R.jsxs)(`div`,{children:[(0,R.jsx)(y,{title:`Scheduler`,description:e===`trader`?`A trading brief on your watchlist before the open or after the close: trade levels, your alerts, hot stocks and the AI read, on the channels you choose. Live price alerts are set on the Trade page.`:`Run the agent pipeline on your watchlists and portfolio automatically and send a report, in the language and detail you choose, to each notification channel.`,actions:(0,R.jsx)(b,{variant:`secondary`,icon:`play`,loading:P,disabled:!X.length,onClick:ge,title:X.length?`Run the saved selection now (${X.length} stocks)`:`Choose what to run and save first`,children:P?`Running…`:`Run now`})}),(0,R.jsxs)(`div`,{className:`mb-6 grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-line bg-line md:grid-cols-4`,children:[(0,R.jsx)(K,{label:`Worker`,value:l?`Running`:`Stopped`,tone:l?`up`:`down`}),(0,R.jsx)(K,{label:`Schedule`,value:t.enabled?`Enabled`:`Disabled`,tone:t.enabled?`up`:`neutral`}),(0,R.jsx)(K,{label:`Next run`,value:ae(t,X.length,ce)}),(0,R.jsx)(K,{label:`Last run`,value:n(t.last_run_at),tone:t.last_run_status==null?void 0:t.last_run_status===`ok`?`up`:`warn`})]}),(0,R.jsxs)(`div`,{className:`grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]`,children:[(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Configuration`,icon:`clock`}),(0,R.jsxs)(d,{className:`space-y-6`,children:[(0,R.jsx)(s,{checked:_.enabled,onChange:e=>$({enabled:e}),label:`Automatic runs`,description:`When off, the watchlist only runs via Run now.`}),(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`Cadence`}),(0,R.jsx)(m,{options:re,value:_.cadence,onChange:e=>$({cadence:e}),size:`sm`}),(0,R.jsx)(`div`,{className:`mt-3`,children:_.cadence===`daily`?(0,R.jsx)(f,{label:`Time of day (24-hour)`,hint:(0,R.jsxs)(R.Fragment,{children:[`In your time zone, `,(0,R.jsx)(`b`,{className:`text-fg`,children:(ce??`…`).replace(/_/g,` `)}),` (`,(0,R.jsx)(w,{to:`/account`,className:`text-accent-fg hover:underline`,children:`change`}),`).`]}),children:(0,R.jsx)(p,{type:`time`,className:`w-40`,value:_.time,onChange:e=>$({time:e.target.value})})}):(0,R.jsx)(f,{label:`Interval (minutes)`,hint:de?void 0:(0,R.jsx)(`span`,{className:`text-down`,children:`A whole number of minutes, 1 or more`}),children:(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,R.jsx)(p,{type:`number`,min:1,step:`1`,value:_.interval,onChange:e=>$({interval:e.target.value}),className:`w-28`}),ie.map(e=>(0,R.jsx)(`button`,{type:`button`,onClick:()=>$({interval:String(e)}),className:c(`rounded-md px-2 py-1 text-xs`,_.interval===String(e)?`bg-accent-soft text-accent-fg`:`bg-raised text-muted hover:text-fg`),children:e>=60?`${e/60}h`:`${e}m`},e))]})})})]}),(0,R.jsx)(oe,{draft:_,catalog:J,targets:ue,onChange:$}),(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`Depth`}),(0,R.jsx)(m,{options:te,value:_.mode,onChange:e=>$({mode:e}),size:`sm`,showHint:!0})]})]}),(0,R.jsxs)(`footer`,{className:`flex items-center justify-between gap-3 border-t border-line px-5 py-3`,children:[(0,R.jsx)(`span`,{className:`text-xs text-muted`,children:Z?`Unsaved changes`:`All changes saved`}),(0,R.jsxs)(`div`,{className:`flex gap-2`,children:[(0,R.jsx)(b,{variant:`ghost`,size:`sm`,disabled:!Z,onClick:()=>S(H(t)),children:`Reset`}),(0,R.jsx)(b,{size:`sm`,loading:E,disabled:!Z||!Q,onClick:he,children:`Save schedule`})]})]})]}),(0,R.jsx)(`div`,{className:`space-y-6 lg:col-span-2`,children:(0,R.jsx)(ne,{draft:{..._,symbols:[...new Set(ue.map(e=>e.symbol))]},options:W,onChange:e=>$(e),footer:(0,R.jsxs)(`footer`,{className:`flex items-center justify-between gap-3 border-t border-line px-5 py-3`,children:[(0,R.jsx)(`span`,{className:`text-xs text-muted`,children:Z?`Unsaved changes`:`All changes saved`}),(0,R.jsx)(b,{size:`sm`,loading:E,disabled:!Z||!Q,onClick:he,children:`Save schedule`})]})})}),(0,R.jsxs)(`div`,{className:`space-y-6 lg:col-start-2 lg:row-start-1`,children:[I&&(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Manual run`,description:I.summary,actions:(0,R.jsxs)(`div`,{className:`flex items-center gap-2`,children:[I.report_token&&(0,R.jsx)(w,{to:`/r/${I.report_token}`,className:`text-xs text-accent-fg hover:underline`,children:`Full report`}),(0,R.jsx)(G,{status:I.status})]})}),(0,R.jsx)(`ul`,{className:`divide-y divide-line`,children:I.results.map(e=>(0,R.jsxs)(`li`,{className:`flex items-start gap-3 px-5 py-3 text-sm`,children:[(0,R.jsx)(`span`,{className:c(`mt-0.5`,e.ok?`text-up`:`text-down`),children:(0,R.jsx)(g,{name:e.ok?`check`:`x`})}),(0,R.jsx)(`span`,{className:`font-mono font-medium`,children:e.symbol}),e.error&&(0,R.jsx)(`span`,{className:`min-w-0 break-words text-xs text-down`,children:e.error})]},e.symbol))})]}),(0,R.jsx)(se,{refreshKey:t.last_run_at}),(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Last run output`,description:t.last_run_at?a(t.last_run_at).toLocaleString():`No runs yet`,actions:t.last_run_status?(0,R.jsx)(G,{status:t.last_run_status}):void 0}),(0,R.jsx)(d,{children:t.last_run_summary?(0,R.jsx)(`pre`,{className:`max-h-96 overflow-auto rounded-lg bg-canvas p-4 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fg/90`,children:t.last_run_summary}):(0,R.jsx)(`p`,{className:`text-xs text-muted`,children:`Output from the most recent scheduled or manual run appears here.`})})]})]})]})]})}function oe({draft:e,catalog:t,targets:n,onChange:r}){let i=t=>r({sources:e.sources.includes(t)?e.sources.filter(e=>e!==t):[...e.sources,t]}),a=t?.watchlists??[],o=t?.portfolios??[],s=(e,t,n)=>e.filter(t).reduce((e,t)=>e+n(t),0),l=s(a,t=>!e.watchlistIds.length||e.watchlistIds.includes(t.id),e=>e.symbols.length),d=s(o,t=>!e.portfolioNames.length||e.portfolioNames.includes(t.name),e=>e.symbols.length),p=(e,t,n,r)=>(0,R.jsx)(`button`,{type:`button`,"aria-pressed":e,onClick:n,className:c(`rounded-full border px-2.5 py-0.5 text-xs font-medium`,e?`border-accent bg-accent-soft text-fg`:`border-line text-muted hover:text-fg`),children:t},r),m=(t,n,r,a)=>{let o=e.sources.includes(t);return(0,R.jsxs)(`div`,{className:c(`rounded-lg border px-3 py-2.5`,o?`border-accent/60 bg-accent-soft/40`:`border-line`),children:[(0,R.jsxs)(`label`,{className:`flex cursor-pointer items-start gap-3`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:o,onChange:()=>i(t),className:`mt-0.5 h-4 w-4 accent-[var(--color-accent)]`}),(0,R.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,R.jsx)(`span`,{className:`block text-sm font-medium`,children:n}),(0,R.jsx)(`span`,{className:`block text-xs text-muted`,children:r})]})]}),o&&a&&(0,R.jsx)(`div`,{className:`mt-2.5 ps-7`,children:a})]})};return(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`What to run`}),(0,R.jsxs)(`div`,{className:`space-y-2`,children:[m(`watchlist`,`Watchlists`,t==null?`Loading…`:a.length?`${l} stocks`:`No watchlists yet`,a.length>1?(0,R.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[p(!e.watchlistIds.length,`All`,()=>r({watchlistIds:[]}),`all`),a.map(t=>p(e.watchlistIds.includes(t.id),`${t.name} · ${t.symbols.length}`,()=>r({watchlistIds:e.watchlistIds.includes(t.id)?e.watchlistIds.filter(e=>e!==t.id):[...e.watchlistIds,t.id]}),String(t.id)))]}):a.length===1&&!l?(0,R.jsxs)(`p`,{className:`text-xs text-muted`,children:[`Your watchlist is empty. Add stocks on the`,` `,(0,R.jsx)(w,{to:`/watchlist`,className:`text-accent-fg hover:underline`,children:`Watchlist`}),` `,`page.`]}):void 0),m(`portfolio`,`Portfolio holdings`,t==null?`Loading…`:o.length?`${d} stocks you own`:`No portfolio yet`,o.length>1?(0,R.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[p(!e.portfolioNames.length,`All`,()=>r({portfolioNames:[]}),`all`),o.map(t=>p(e.portfolioNames.includes(t.name),`${t.name} · ${t.symbols.length}`,()=>r({portfolioNames:e.portfolioNames.includes(t.name)?e.portfolioNames.filter(e=>e!==t.name):[...e.portfolioNames,t.name]}),t.name))]}):void 0),m(`custom`,`Custom symbols`,e.symbols.length?`${e.symbols.length} symbols listed here`:`Type symbols just for this schedule`,(0,R.jsxs)(`div`,{className:`space-y-3`,children:[(0,R.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-[140px_minmax(0,1fr)]`,children:[(0,R.jsx)(f,{label:`Market`,children:(0,R.jsx)(u,{options:F,value:e.market,onChange:e=>r({market:e.target.value})})}),(0,R.jsx)(f,{label:`Symbols`,hint:`Enter or comma to add · Backspace removes the last`,children:(0,R.jsx)(S,{values:e.symbols,onChange:e=>r({symbols:e}),placeholder:`AAPL, MSFT, NVDA`})})]}),(0,R.jsx)(q,{market:e.market,onAdd:t=>!e.symbols.includes(t)&&r({symbols:[...e.symbols,t]})})]}))]}),(0,R.jsx)(`p`,{className:c(`mt-2 text-xs`,e.sources.length&&n.length?`text-muted`:`text-warn`),children:e.sources.length?n.length?`Each run covers ${n.length} stock${n.length===1?``:`s`}${e.sources.length>1?` (duplicates counted once)`:``}: ${n.slice(0,12).map(e=>e.symbol).join(`, `)}${n.length>12?`, …`:``}`:`The chosen sources have no stocks yet.`:`Choose at least one source.`})]})}function se({refreshKey:e}){let[t,r]=(0,L.useState)([]);return(0,L.useEffect)(()=>{E(8).then(r).catch(()=>r([]))},[e]),t.length?(0,R.jsxs)(h,{children:[(0,R.jsx)(v,{title:`Full reports`,description:`Every monitored stock with levels and a 1-week range (Smart messaging runs).`}),(0,R.jsx)(`ul`,{className:`divide-y divide-line`,children:t.map(e=>(0,R.jsx)(`li`,{children:(0,R.jsxs)(w,{to:`/r/${e.token}`,className:`flex items-center gap-3 px-5 py-2.5 text-sm hover:bg-raised`,children:[(0,R.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,R.jsx)(`span`,{className:`text-xs text-muted`,children:n(e.created_at)}),(0,R.jsx)(g,{name:`chevron`,className:`h-3.5 w-3.5 text-faint`})]})},e.token))})]}):null}function G({status:e}){return(0,R.jsx)(_,{tone:e===`ok`?`up`:e===`failed`?`down`:`warn`,children:e.replace(/_/g,` `)})}function K({label:e,value:t,tone:n}){return(0,R.jsxs)(`div`,{className:`bg-surface px-5 py-4`,children:[(0,R.jsx)(`div`,{className:`text-xs font-medium text-muted`,children:e}),(0,R.jsxs)(`div`,{className:`mt-1 flex items-center gap-2 text-sm font-semibold`,children:[n&&(0,R.jsx)(l,{tone:n}),(0,R.jsx)(`span`,{className:`truncate`,children:t})]})]})}function q({market:e,onAdd:t}){let[n,r]=(0,L.useState)(``);return(0,R.jsx)(I,{value:n,onChange:r,onSelect:e=>{t(e.symbol),r(``)},market:e,exclude:[`mf`],placeholder:`Search ${e===`global`?`all markets`:`the `+e.replace(`_`,` `)+` market`} to add symbols`})}export{W as default};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,l as n,n as r,p as i,u as a}from"./format-d8InM0Zw.js";import{t as o}from"./toast-DDradTZw.js";import{C as s,D as c,O as l,S as u,T as d,_ as f,a as p,b as m,c as h,f as g,h as _,i as v,l as y,n as b,o as x,p as S,r as C,t as w,y as T}from"./ui-gsFb8B2m.js";import{C as E,E as D,S as O,T as k,a as A,g as ee,i as te,o as ne,s as j,v as re,w as ie,x as ae}from"./index-CKAnq-Or.js";var M=e(t(),1),N=e=>e===`password`||e===`secret_list`,P=[{name:`Telegram`,fields:[{attr:`telegram_bot_token`,label:`Bot token`,kind:`password`},{attr:`telegram_chat_id`,label:`Chat ID (send /start to your bot to get it; comma-separate several)`,kind:`text`},{attr:`telegram_message_thread_id`,label:`Topic ID (optional, for forum groups)`,kind:`text`}]},{name:`WhatsApp`,fields:[{attr:`whatsapp_phone`,label:`Your WhatsApp number with country code (e.g. +919876543210)`,kind:`text`},{attr:`whatsapp_callmebot_apikey`,label:`CallMeBot API key (message +34 644 51 95 23 'I allow callmebot to send me messages')`,kind:`password`}]},{name:`Twilio SMS/WhatsApp`,fields:[{attr:`twilio_account_sid`,label:`Account SID`,kind:`text`},{attr:`twilio_auth_token`,label:`Auth token`,kind:`password`},{attr:`twilio_from`,label:`From number (e.g. +15551234567, or whatsapp:+14155238886)`,kind:`text`},{attr:`twilio_to`,label:`To numbers (comma-separated; prefix whatsapp: for WhatsApp)`,kind:`list`}]},{name:`Discord`,fields:[{attr:`discord_webhook_url`,label:`Webhook URL`,kind:`text`}]},{name:`Slack`,fields:[{attr:`slack_webhook_url`,label:`Webhook URL`,kind:`text`}]},{name:`Email`,fields:[{attr:`email_sender`,label:`Sender address`,kind:`text`},{attr:`email_reports_sender`,label:`Reports & alerts sender (blank = sender address)`,kind:`text`},{attr:`email_username`,label:`SMTP username (blank = sender address; Gmail send-as: your Gmail)`,kind:`text`},{attr:`email_password`,label:`Password / app password`,kind:`password`},{attr:`email_receivers`,label:`Recipients (comma-separated)`,kind:`list`},{attr:`email_smtp_server`,label:`SMTP server (blank = auto-detect)`,kind:`text`},{attr:`email_smtp_port`,label:`SMTP port (blank = auto-detect)`,kind:`int`},{attr:`email_smtp_ssl`,label:`Force SSL (unchecked = auto-detect)`,kind:`bool`}]},{name:`DingTalk`,fields:[{attr:`dingtalk_webhook_url`,label:`Webhook URL`,kind:`text`},{attr:`dingtalk_secret`,label:`Secret (optional signing)`,kind:`password`}]},{name:`Feishu`,fields:[{attr:`feishu_webhook_url`,label:`Webhook URL`,kind:`text`},{attr:`feishu_webhook_secret`,label:`Secret (optional signing)`,kind:`password`}]},{name:`WeChat`,fields:[{attr:`wechat_webhook_url`,label:`Group robot webhook URL`,kind:`text`}]},{name:`Pushover`,fields:[{attr:`pushover_user_key`,label:`User key`,kind:`text`},{attr:`pushover_api_token`,label:`API token`,kind:`password`}]},{name:`ntfy`,fields:[{attr:`ntfy_url`,label:`Topic URL (e.g. https://ntfy.sh/mytopic)`,kind:`text`},{attr:`ntfy_token`,label:`Access token (optional)`,kind:`password`}]},{name:`Gotify`,fields:[{attr:`gotify_url`,label:`Server URL`,kind:`text`},{attr:`gotify_token`,label:`App token`,kind:`password`}]},{name:`PushPlus`,fields:[{attr:`pushplus_token`,label:`Token`,kind:`password`},{attr:`pushplus_topic`,label:`Topic (optional, for group push)`,kind:`text`}]},{name:`ServerChan3`,fields:[{attr:`serverchan3_sendkey`,label:`SendKey`,kind:`password`}]},{name:`AstrBot`,fields:[{attr:`astrbot_url`,label:`Instance URL`,kind:`text`},{attr:`astrbot_token`,label:`Token (optional)`,kind:`password`}]},{name:`Microsoft Teams`,fields:[{attr:`teams_webhook_url`,label:`Workflows webhook URL (Teams channel > Workflows > 'Post to a channel when a webhook request is received')`,kind:`text`}]},{name:`Google Chat`,fields:[{attr:`google_chat_webhook_url`,label:`Space webhook URL (Space > Apps & integrations > Webhooks)`,kind:`text`}]},{name:`Matrix`,fields:[{attr:`matrix_homeserver`,label:`Homeserver URL (e.g. https://matrix.org)`,kind:`text`},{attr:`matrix_access_token`,label:`Access token`,kind:`password`},{attr:`matrix_room_id`,label:`Room ID (e.g. !abc123:matrix.org)`,kind:`text`}]},{name:`Signal`,fields:[{attr:`signal_api_url`,label:`signal-cli REST API URL (e.g. http://localhost:8080)`,kind:`text`},{attr:`signal_number`,label:`Sending number linked to signal-cli (e.g. +919876543210)`,kind:`text`},{attr:`signal_recipients`,label:`Recipients (comma-separated numbers or group IDs)`,kind:`list`}]},{name:`Bark (iOS)`,fields:[{attr:`bark_url`,label:`Device URL from the Bark app (e.g. https://api.day.app/yourkey)`,kind:`password`}]},{name:`Pushbullet`,fields:[{attr:`pushbullet_token`,label:`Access token`,kind:`password`}]},{name:`Apprise`,fields:[{attr:`apprise_urls`,label:`Apprise URLs for 100+ other services (comma-separated; needs 'pip install apprise')`,kind:`list`}]},{name:`Webhook`,fields:[{attr:`webhook_url`,label:`URL`,kind:`text`},{attr:`webhook_headers`,label:`Extra headers (JSON, e.g. {"Authorization": "Bearer x"})`,kind:`multiline`}]}];function oe(e){return typeof e==`object`&&!!e&&`is_set`in e}async function F(){return(await l.get(`/system-config/notifications`)).data}async function I(e){return(await l.put(`/system-config/notifications`,e)).data}async function L(e){return(await l.post(`/system-config/notifications/test`,e)).data}async function R(){return(await l.get(`/system-config/notification-routing`)).data}async function z(e){return(await l.put(`/system-config/notification-routing`,e)).data}var B=i();function V(){let[e,t]=(0,M.useState)(null),[n,i]=(0,M.useState)({}),[a,s]=(0,M.useState)(!1);if((0,M.useEffect)(()=>{R().then(e=>{t(e),i(e.routes)}).catch(e=>o.error(r(e)))},[]),!e)return(0,B.jsx)(T,{className:`h-40 w-full max-w-3xl`});let l=JSON.stringify(n)!==JSON.stringify(e.routes);function u(t,n){i(r=>{let i=r[t]?.length?r[t]:e.channels,a=i.includes(n)?i.filter(e=>e!==n):[...i,n];return{...r,[t]:a.length===e.channels.length?[]:a}})}async function d(){s(!0);try{let e=await z(n);t(e),i(e.routes),o.success(`Routing saved`)}catch(e){o.error(r(e))}finally{s(!1)}}return(0,B.jsxs)(v,{className:`mt-6 max-w-3xl`,children:[(0,B.jsx)(x,{title:`Routing`,description:`Choose which channels receive each kind of message. All channels are on by default.`,icon:`send`}),(0,B.jsx)(p,{children:e.channels.length===0?(0,B.jsx)(`p`,{className:`text-xs text-muted`,children:`Configure at least one channel above first.`}):(0,B.jsx)(`div`,{className:`overflow-x-auto`,children:(0,B.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{className:`text-xs text-muted`,children:[(0,B.jsx)(`th`,{className:`py-2 pe-4 text-start font-medium`,children:`Message`}),e.channels.map(e=>(0,B.jsx)(`th`,{className:`px-2 py-2 text-center font-medium capitalize`,children:e},e))]})}),(0,B.jsx)(`tbody`,{className:`divide-y divide-line`,children:e.purposes.map(t=>{let r=n[t.id]??[];return(0,B.jsxs)(`tr`,{children:[(0,B.jsxs)(`td`,{className:`py-2.5 pe-4`,children:[(0,B.jsx)(`div`,{className:`font-medium`,children:t.label}),(0,B.jsx)(`div`,{className:`text-xs text-muted`,children:t.description})]}),e.channels.map(e=>{let n=r.length===0||r.includes(e);return(0,B.jsx)(`td`,{className:`px-2 py-2.5 text-center`,children:(0,B.jsx)(`input`,{type:`checkbox`,checked:n,onChange:()=>u(t.id,e),"aria-label":`${t.label} via ${e}`,className:c(`h-4 w-4 accent-[var(--color-accent)]`)})},e)})]},t.id)})})]})})}),(0,B.jsxs)(`footer`,{className:`flex items-center justify-between gap-3 border-t border-line px-5 py-3`,children:[(0,B.jsx)(`span`,{className:`text-xs text-muted`,children:l?`Unsaved changes`:`All changes saved`}),(0,B.jsx)(C,{size:`sm`,loading:a,disabled:!l,onClick:d,children:`Save routing`})]})]})}async function H(){return(await l.get(`/push/vapid-public-key`)).data.public_key}async function U(){return(await l.get(`/push/subscriptions`)).data}async function W(e,t){return(await l.post(`/push/subscriptions`,{...e,label:t})).data}async function G(e){await l.post(`/push/unsubscribe`,{endpoint:e})}async function K(e){await l.delete(`/push/subscriptions/${e}`)}async function q(){return(await l.post(`/push/test`)).data}function se(e){let t=(e+`=`.repeat((4-e.length%4)%4)).replace(/-/g,`+`).replace(/_/g,`/`),n=atob(t),r=new Uint8Array(new ArrayBuffer(n.length));for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return r}function J(){let e=navigator.userAgent,t=/Edg\//.test(e)?`Edge`:/Firefox\//.test(e)?`Firefox`:/Chrome\//.test(e)?`Chrome`:/Safari\//.test(e)?`Safari`:`Browser`,n=/Android/.test(e)?`Android`:/iPhone|iPad/.test(e)?`iOS`:/Mac OS X/.test(e)?`macOS`:/Windows/.test(e)?`Windows`:/Linux/.test(e)?`Linux`:``;return n?`${t} on ${n}`:t}var Y=typeof window<`u`&&`serviceWorker`in navigator&&`PushManager`in window&&`Notification`in window;function ce(){let[e,t]=(0,M.useState)(null),[i,a]=(0,M.useState)(null),[s,c]=(0,M.useState)(!1),[l,u]=(0,M.useState)(Y?Notification.permission:`unsupported`),d=(0,M.useCallback)(async()=>{try{t(await U())}catch(e){o.error(r(e))}if(Y){let e=await(await navigator.serviceWorker.getRegistration(`/`))?.pushManager.getSubscription();a(e?.endpoint??null)}},[]);(0,M.useEffect)(()=>{d()},[d]);async function f(){c(!0);try{let e=await Notification.requestPermission();if(u(e),e!==`granted`){o.error(`Notifications are blocked for this site. Allow them in the browser’s site settings.`);return}let t=await navigator.serviceWorker.register(`/sw.js`,{scope:`/`});await navigator.serviceWorker.ready;let n=await H(),r=await t.pushManager.getSubscription();r||=await t.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:se(n)}),await W(r.toJSON(),J()),o.success(`Push notifications enabled on this device`),await d()}catch(e){o.error(r(e))}finally{c(!1)}}async function m(){c(!0);try{let e=await(await navigator.serviceWorker.getRegistration(`/`))?.pushManager.getSubscription();e&&(await G(e.endpoint),await e.unsubscribe()),o.success(`Push notifications turned off on this device`),await d()}catch(e){o.error(r(e))}finally{c(!1)}}async function h(){c(!0);try{let e=await q();e.sent?o.success(`Test push sent - it should appear in a few seconds`):o.error(e.message)}catch(e){o.error(r(e))}finally{c(!1)}}let g=i!=null,_=typeof window<`u`&&window.isSecureContext;return(0,B.jsxs)(v,{className:`mb-6 max-w-3xl`,children:[(0,B.jsx)(x,{title:`Push notifications`,description:`Get reports and alerts as system notifications from MarketMyna itself, even with the tab closed.`,icon:`bell`,actions:e&&e.length>0?(0,B.jsx)(C,{variant:`secondary`,size:`sm`,icon:`send`,loading:s,onClick:h,children:`Send test`}):void 0}),(0,B.jsxs)(p,{className:`space-y-4`,children:[Y?_?(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 rounded-lg border border-line px-4 py-3`,children:[(0,B.jsxs)(`div`,{children:[(0,B.jsxs)(`div`,{className:`flex items-center gap-2 text-sm font-medium`,children:[`This device `,(0,B.jsx)(b,{tone:g?`up`:`neutral`,children:g?`on`:`off`})]}),(0,B.jsx)(`p`,{className:`text-xs text-muted`,children:l===`denied`?`Notifications are blocked for this site - allow them in the browser’s site settings.`:J()})]}),g?(0,B.jsx)(C,{variant:`ghost`,size:`sm`,loading:s,onClick:m,children:`Turn off`}):(0,B.jsx)(C,{size:`sm`,icon:`bell`,loading:s,disabled:l===`denied`,onClick:f,children:`Enable on this device`})]}):(0,B.jsx)(w,{tone:`warn`,title:`Needs HTTPS`,children:`Browsers only allow push on https:// or http://localhost. Open MarketMyna through HTTPS (e.g. a reverse proxy or Tailscale/Cloudflare tunnel) to enable it on other devices.`}):(0,B.jsx)(w,{tone:`warn`,title:`This browser can't receive push notifications`,children:`Use Chrome, Edge or Firefox on desktop/Android. On iPhone/iPad (iOS 16.4+), open MarketMyna in Safari, tap Share → Add to Home Screen, then enable push from the home-screen app.`}),e&&e.length>0&&(0,B.jsxs)(`div`,{children:[(0,B.jsxs)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:[`Devices receiving push (`,e.length,`)`]}),(0,B.jsx)(`ul`,{className:`divide-y divide-line rounded-lg border border-line`,children:e.map(e=>(0,B.jsxs)(`li`,{className:`flex items-center gap-3 px-3 py-2 text-sm`,children:[(0,B.jsx)(y,{name:`bell`,className:`h-4 w-4 text-faint`}),(0,B.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.label}),(0,B.jsx)(`span`,{className:`hidden text-xs text-faint sm:inline`,children:e.last_success_at?`last push ${n(e.last_success_at)}`:`added ${n(e.created_at)}`}),(0,B.jsx)(`button`,{type:`button`,onClick:async()=>{await K(e.id),await d()},className:`rounded-md p-1 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Remove ${e.label}`,children:(0,B.jsx)(y,{name:`x`})})]},e.id))})]})]})]})}var X={gemini:`Google Gemini`,groq:`Groq`,openrouter:`OpenRouter`,openai:`OpenAI`,anthropic:`Anthropic`,deepseek:`DeepSeek`,mistral:`Mistral`};function le(e){return e?a(e).toLocaleDateString(void 0,{day:`numeric`,month:`short`,year:`numeric`}):`—`}function ue(){let e=ee(e=>e.setMe),[t,n]=(0,M.useState)(null),[i,a]=(0,M.useState)(``),[s,c]=(0,M.useState)(!1);(0,M.useEffect)(()=>{ae().then(n).catch(e=>o.error(r(e)))},[]);async function l(t){n(t),e(await E())}async function u(e){e.preventDefault(),c(!0);try{let e=new Set(t?.keys.map(e=>e.id)),n=await ie(i);await l(n),a(``);let r=n.keys.filter(t=>!e.has(t.id));r.length===1?o.success(`${X[r[0].provider]??r[0].provider} key detected and saved.`):r.length>1?o.success(`${r.length} keys detected and saved.`):o.success(`Already saved.`);for(let e of n.errors??[])o.error(e)}catch(e){o.error(r(e))}finally{c(!1)}}async function f(e){try{await l(await re(e)),o.success(`Key removed.`)}catch(e){o.error(r(e))}}return(0,B.jsxs)(v,{children:[(0,B.jsx)(x,{title:`AI keys`,icon:`cpu`,description:`Paste a key and the app works out the provider and picks a model, a free one where the key allows it. Stored encrypted; only the last 4 characters are ever shown.`}),(0,B.jsxs)(p,{className:`space-y-4`,children:[t?.keys.length?(0,B.jsxs)(B.Fragment,{children:[t.keys.length>1&&(0,B.jsx)(`p`,{className:`text-xs text-muted`,children:`Tried in this order: when a key fails or hits its limit, the next one answers.`}),(0,B.jsx)(`ol`,{className:`divide-y divide-line rounded-lg border border-line`,children:t.keys.map((e,n)=>(0,B.jsxs)(`li`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1 px-3 py-2 text-sm`,children:[t.keys.length>1&&(0,B.jsx)(`span`,{className:`tabular w-4 text-xs text-faint`,children:n+1}),(0,B.jsx)(`span`,{className:`font-medium`,children:X[e.provider]??e.provider}),(0,B.jsxs)(`span`,{className:`tabular text-muted`,children:[`•••• `,e.last4]}),e.free===!0&&(0,B.jsx)(b,{tone:`up`,children:`Free`}),e.free===!1&&(0,B.jsx)(b,{children:`Paid`}),(0,B.jsxs)(`span`,{className:`text-xs text-faint`,children:[`added `,le(e.added_at)]}),(0,B.jsx)(C,{size:`sm`,variant:`ghost`,icon:`trash`,className:`ms-auto`,onClick:()=>f(e.id),children:`Remove`}),(e.model||e.note)&&(0,B.jsxs)(`p`,{className:`w-full text-xs text-muted`,children:[e.model&&(0,B.jsx)(`span`,{className:`font-mono`,children:e.model.split(`/`).slice(1).join(`/`)}),e.model&&e.note&&` · `,e.note]})]},e.id))})]}):(0,B.jsx)(`p`,{className:`text-sm text-muted`,children:`No keys yet: AI features are off until you add one. (Running a local model instead? Set LLM_MODEL and OLLAMA_BASE_URL in .env, see .env.example.)`}),(0,B.jsxs)(`form`,{onSubmit:u,className:`grid gap-3 sm:grid-cols-[1fr_auto] sm:items-start`,children:[(0,B.jsx)(h,{label:`API key`,hint:`Anthropic, Google Gemini, Groq, Mistral or OpenRouter. Paste several at once (one per line) for automatic fallback.`,children:(0,B.jsx)(d,{autoComplete:`off`,spellCheck:!1,rows:i.includes(`
|
|
2
|
+
`)?3:1,value:i,onChange:e=>a(e.target.value),placeholder:`Paste key`,className:`min-h-9 resize-y py-2 font-mono text-xs [-webkit-text-security:disc]`})}),(0,B.jsx)(C,{type:`submit`,className:`sm:mt-[calc(var(--text-xs--line-height)+0.375rem)]`,loading:s,disabled:i.trim().length<8,children:s?`Checking…`:`Save key`})]})]})]})}var de={finnhub:`globe`,market_data:`candles`,social:`chat`};function fe(){let[e,t]=(0,M.useState)(null),n=(0,M.useCallback)(()=>{O().then(t).catch(e=>o.error(r(e)))},[]);return(0,M.useEffect)(n,[n]),e?(0,B.jsxs)(`div`,{className:`space-y-6`,children:[(0,B.jsx)(w,{tone:`accent`,title:`All optional`,children:`The app works without any of these. Keys are saved encrypted in the app's config file; you can set them as environment variables instead (FINNHUB_API_KEY, …), which then show as "set on server".`}),e.groups.map(e=>(0,B.jsx)(pe,{group:e,onSaved:t},e.id))]}):(0,B.jsx)(T,{className:`h-64`})}function pe({group:e,onSaved:t}){let[n,i]=(0,M.useState)({}),[a,s]=(0,M.useState)(null),c=Object.keys(n).length>0;async function l(a=n){s(`save`);try{t(await D(a)),i({}),o.success(`${e.title} saved`)}catch(e){o.error(r(e))}finally{s(null)}}async function u(){s(`test`);try{o.success((await k(e.id)).message)}catch(e){o.error(r(e))}finally{s(null)}}return(0,B.jsxs)(v,{children:[(0,B.jsx)(x,{title:e.title,description:e.help,icon:de[e.id]??`settings`}),(0,B.jsxs)(p,{className:`space-y-4`,children:[(0,B.jsx)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:e.fields.map(e=>(0,B.jsx)(me,{field:e,value:n[e.name],onChange:t=>i(n=>({...n,[e.name]:t})),onClear:()=>l({[e.name]:null})},e.name))}),(0,B.jsxs)(`div`,{className:`flex flex-wrap justify-end gap-2`,children:[(0,B.jsx)(C,{variant:`secondary`,disabled:a!==null||c,onClick:u,children:a===`test`?`Testing…`:`Test`}),(0,B.jsx)(C,{disabled:!c||a!==null,onClick:()=>l(),children:a===`save`?`Saving…`:`Save`})]})]})]})}function me({field:e,value:t,onChange:n,onClear:r}){return e.from_env?(0,B.jsx)(h,{label:e.label,hint:`Set by an environment variable on the server.`,children:(0,B.jsx)(g,{disabled:!0,value:e.kind===`secret`?`••••••••`:String(e.value??``)})}):e.kind===`bool`?(0,B.jsx)(`div`,{className:`sm:col-span-2`,children:(0,B.jsx)(s,{label:e.label,checked:t===void 0?!!e.value:!!t,onChange:e=>n(e)})}):e.kind===`secret`?(0,B.jsx)(h,{label:e.label,hint:e.is_set?(0,B.jsxs)(`span`,{children:[`Saved`,e.last4?` (ends ${e.last4})`:``,`. Type to replace, or`,` `,(0,B.jsx)(`button`,{type:`button`,className:`underline`,onClick:r,children:`remove`}),`.`]}):`Not set.`,children:(0,B.jsx)(_,{placeholder:e.is_set?`••••••••`:``,value:t??``,onChange:e=>n(e.target.value)})}):(0,B.jsx)(h,{label:e.label,children:(0,B.jsx)(g,{value:String(t===void 0?e.value??``:t??``),onChange:e=>n(e.target.value)})})}var he={source:`Installed from source (git)`,zip:`Installed from a release zip`,package:`Installed with pipx / pip`},ge=[{value:`5`,label:`Every 5 minutes`},{value:`60`,label:`Every hour`},{value:`120`,label:`Every 2 hours`},{value:`0`,label:`Off`}],Z=e=>new Promise(t=>window.setTimeout(t,e));async function Q(){await Z(4e3);for(let e=0;e<150;e++)try{return await l.get(`/health`,{timeout:3e3}),!0}catch{await Z(2e3)}return!1}function _e(){let[e,t]=(0,M.useState)(null),[i,a]=(0,M.useState)(`5`),[s,c]=(0,M.useState)(!1),[l,u]=(0,M.useState)(null),[d,h]=(0,M.useState)(`idle`),[g,_]=(0,M.useState)([]);(0,M.useEffect)(()=>{ne().then(e=>{e.checked_at&&t(e),e.settings&&a(String(e.settings.interval_minutes))}).catch(()=>{})},[]);async function y(){c(!0),u(null);try{let e=await A(!0);if(t(e),e.settings&&a(String(e.settings.interval_minutes)),e.error)return;e.update_available?o.info(e.release_available?`MarketMyna ${e.latest} is available`:`New code is on GitHub`):o.success(`You're on the latest version`)}catch(e){u(r(e))}finally{c(!1)}}async function S(e){let t=i;a(e);try{await j({interval_minutes:Number(e)}),o.success(e===`0`?`Automatic checks off`:`Saved`)}catch(e){a(t),o.error(r(e))}}async function T(){h(`installing`),u(null),_([]);try{let e=await te();if(_(e.log),!e.restarting){h(`idle`),o.success(`Already up to date`);return}h(`restarting`),await Q()?window.location.reload():(h(`idle`),u(`MarketMyna did not come back after the update. Check the terminal it runs in, then start it again.`))}catch(e){h(`idle`),u(r(e))}}async function E(e){try{await navigator.clipboard.writeText(e),o.success(`Copied`)}catch{o.error(`Could not copy - select the text instead`)}}let D=e?.code,O=d===`installing`||d===`restarting`;return(0,B.jsxs)(v,{children:[(0,B.jsx)(x,{title:`Updates`,description:e?`Version ${e.current} · ${he[e.install]}${D?` · commit ${D.local_sha}`:``}`:`Checks github.com/pryndor/MarketMyna for a new release or newer code.`,actions:(0,B.jsx)(C,{variant:`secondary`,size:`sm`,icon:`refresh`,loading:s,disabled:O,onClick:y,children:`Check for updates`})}),(0,B.jsxs)(p,{className:`space-y-4`,children:[(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1.5`,children:[(0,B.jsx)(`label`,{htmlFor:`update-interval`,className:`text-sm text-muted`,children:`Check GitHub automatically`}),(0,B.jsx)(f,{id:`update-interval`,options:ge,value:i,onChange:e=>void S(e.target.value),className:`w-auto`}),(0,B.jsx)(`span`,{className:`text-xs text-faint`,children:`The app checks while it runs; a new version also shows in the sidebar.`})]}),l&&(0,B.jsx)(w,{title:`Update problem`,children:(0,B.jsx)(`span`,{className:`whitespace-pre-wrap`,children:l})}),e?.error&&(0,B.jsx)(w,{title:`Could not check for updates`,children:e.error}),e&&!e.error&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 text-sm`,children:[(0,B.jsx)(b,{tone:e.update_available?`accent`:`up`,children:e.update_available?`Update available`:`Up to date`}),e.checked_at&&(0,B.jsxs)(`span`,{className:`text-xs text-faint`,children:[`last checked `,n(new Date(e.checked_at*1e3).toISOString())]})]}),(0,B.jsxs)(`dl`,{className:`divide-y divide-line rounded-lg border border-line text-sm`,children:[(0,B.jsxs)(`div`,{className:`flex flex-wrap items-baseline justify-between gap-2 px-3 py-2`,children:[(0,B.jsx)(`dt`,{className:`text-muted`,children:`Latest release`}),(0,B.jsxs)(`dd`,{className:`flex flex-wrap items-baseline gap-2`,children:[e.latest?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:e.release_available?`font-semibold text-accent-fg`:``,children:e.latest}),(0,B.jsx)(`span`,{className:`text-xs text-faint`,children:e.release_available?`newer than your ${e.current}`:`you have ${e.current}`})]}):(0,B.jsx)(`span`,{className:`text-faint`,children:`none published yet`}),(0,B.jsxs)(`a`,{href:e.release?.url??e.releases_url,target:`_blank`,rel:`noreferrer`,className:`text-xs font-medium text-accent hover:underline`,children:[e.release_available?`What's new`:`Releases`,` ↗`]})]})]}),D&&(0,B.jsxs)(`div`,{className:`flex flex-wrap items-baseline justify-between gap-2 px-3 py-2`,children:[(0,B.jsx)(`dt`,{className:`text-muted`,children:`Latest code on main`}),(0,B.jsxs)(`dd`,{className:`flex min-w-0 flex-wrap items-baseline gap-2`,children:[(0,B.jsx)(`span`,{className:`font-mono text-xs`,children:D.remote_sha}),(0,B.jsx)(`span`,{className:`text-xs text-faint`,children:D.update_available?`newer than your ${D.local_sha}${D.remote_date?` · ${n(D.remote_date)}`:``}`:D.remote_sha===D.local_sha?`same as yours`:`yours (${D.local_sha}) is newer`}),D.url&&(0,B.jsx)(`a`,{href:D.url,target:`_blank`,rel:`noreferrer`,className:`text-xs font-medium text-accent hover:underline`,children:`View ↗`})]})]}),D?.update_available&&D.message&&(0,B.jsxs)(`div`,{className:`px-3 py-2 text-xs text-muted`,children:[`“`,D.message,`”`]})]}),e.update_available&&e.can_apply&&(0,B.jsxs)(`div`,{className:`rounded-lg border border-accent/40 bg-accent-soft/40 p-4`,children:[d===`idle`&&(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,B.jsx)(`p`,{className:`text-sm`,children:`Install the update and restart MarketMyna. Your data, keys and settings are kept.`}),(0,B.jsx)(C,{icon:`refresh`,onClick:()=>h(`confirm`),children:`Update now`})]}),d===`confirm`&&(0,B.jsxs)(`div`,{className:`space-y-3`,children:[(0,B.jsxs)(`p`,{className:`text-sm`,children:[e.install===`source`?`MarketMyna moves this copy to the latest code from GitHub (your current commit is kept on a backup branch), installs any new requirements, rebuilds the pages and restarts. It stops if you have edited its files.`:`MarketMyna upgrades its package from PyPI and restarts.`,` `,`The app is offline for a minute or two while it restarts.`]}),(0,B.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,B.jsx)(C,{icon:`refresh`,onClick:()=>void T(),children:`Yes, update and restart`}),(0,B.jsx)(C,{variant:`ghost`,onClick:()=>h(`idle`),children:`Cancel`})]})]}),O&&(0,B.jsxs)(`div`,{className:`flex items-center gap-2 text-sm`,children:[(0,B.jsx)(m,{className:`h-4 w-4 text-accent-fg`}),d===`installing`?`Installing the update…`:`Restarting MarketMyna - this page reloads by itself when it is back (rebuilding the pages can take a minute).`]})]}),e.update_available&&!e.can_apply&&(0,B.jsxs)(`div`,{className:`space-y-2`,children:[(0,B.jsx)(`p`,{className:`text-xs text-muted`,children:`To update, stop MarketMyna and run (your data is kept):`}),e.commands.map(e=>(0,B.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,B.jsx)(`code`,{className:`min-w-0 flex-1 break-all rounded-md bg-canvas px-3 py-2 font-mono text-xs`,children:e}),(0,B.jsx)(C,{variant:`ghost`,size:`sm`,onClick:()=>E(e),title:`Copy`,children:`Copy`})]},e))]})]}),g.length>0&&(0,B.jsxs)(`details`,{className:`text-xs`,open:d===`idle`&&!!l,children:[(0,B.jsx)(`summary`,{className:`cursor-pointer text-muted`,children:`Update log`}),(0,B.jsx)(`pre`,{className:`mt-2 max-h-64 overflow-auto whitespace-pre-wrap rounded-md bg-canvas p-3 font-mono text-[11px]`,children:g.join(`
|
|
3
|
+
`)})]})]})]})}function ve(){let[e,t]=(0,M.useState)(`ai`);return(0,B.jsxs)(`div`,{children:[(0,B.jsx)(S,{title:`Settings`,description:`AI keys, where reports and alerts go, and optional data sources.`}),(0,B.jsx)(`div`,{className:`no-scrollbar -mx-4 mb-6 flex gap-1 overflow-x-auto border-b border-line px-4 sm:mx-0 sm:px-0`,children:[[`ai`,`AI keys`,`cpu`],[`notifications`,`Notifications`,`bell`],[`data`,`Data sources`,`candles`]].map(([n,r,i])=>(0,B.jsxs)(`button`,{type:`button`,onClick:()=>t(n),className:c(`-mb-px flex shrink-0 items-center gap-2 whitespace-nowrap border-b-2 px-3 py-2.5 text-sm font-medium`,e===n?`border-accent text-fg`:`border-transparent text-muted hover:text-fg`),children:[(0,B.jsx)(y,{name:i}),` `,r]},n))}),e===`ai`?(0,B.jsx)(ue,{}):e===`data`?(0,B.jsx)(fe,{}):(0,B.jsxs)(`div`,{className:`space-y-6`,children:[(0,B.jsx)(ce,{}),(0,B.jsx)(Te,{}),(0,B.jsx)(V,{})]}),(0,B.jsx)(`div`,{className:`mt-8`,children:(0,B.jsx)(_e,{})}),(0,B.jsxs)(`p`,{className:`mt-4 text-xs text-muted`,children:[`MarketMyna is open source under the Apache License 2.0.`,` `,(0,B.jsx)(`a`,{className:`underline hover:text-fg`,href:`https://github.com/pryndor/MarketMyna`,target:`_blank`,rel:`noreferrer`,children:`Source code`})]})]})}function ye(e){let[t,n]=(0,M.useState)({}),[r,i]=(0,M.useState)({}),[a,o]=(0,M.useState)({}),[s,c]=(0,M.useState)(new Set),l=(0,M.useCallback)(t=>{let r={},a={};for(let n of e){let e=t[n.attr];oe(e)?(a[n.attr]=e.is_set,r[n.attr]=``):r[n.attr]=e==null?``:Array.isArray(e)?e.join(`, `):String(e)}n(r),i(r),o(a),c(new Set)},[e]),u=(0,M.useMemo)(()=>{let n={};for(let i of e){let e=r[i.attr]??``;if(N(i.kind)){let t=i.kind===`secret_list`;s.has(i.attr)?n[i.attr]=t?[]:``:e!==``&&(n[i.attr]=t?e.split(`,`).map(e=>e.trim()).filter(Boolean):e)}else e!==(t[i.attr]??``)&&(n[i.attr]=be(i,e))}return n},[e,r,t,s]);return{values:r,secretSet:a,cleared:s,payload:u,dirty:Object.keys(u).length>0,hydrate:l,set:(e,t)=>{i(n=>({...n,[e]:t})),c(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},clearSecret:e=>{i(t=>({...t,[e]:``})),c(t=>new Set(t).add(e))},reset:()=>{i(t),c(new Set)}}}function be(e,t){let n=t.trim();return e.kind===`bool`?t===`true`:n===``?null:e.kind===`int`?Number.isFinite(Number(n))?parseInt(n,10):null:e.kind===`float`?Number.isFinite(Number(n))?parseFloat(n):null:e.kind===`list`?n.split(`,`).map(e=>e.trim()).filter(Boolean):t}function xe(e){let t=e.match(/^(.*?)\s*\((.*)\)$/);return t?[t[1],t[2]]:[e,void 0]}function Se({spec:e,form:t}){let[n,r]=xe(e.label),i=t.values[e.attr]??``;if(e.kind===`bool`)return(0,B.jsx)(s,{checked:i===`true`,onChange:n=>t.set(e.attr,String(n)),label:n,description:r});if(N(e.kind)){let a=t.secretSet[e.attr]&&!t.cleared.has(e.attr);return(0,B.jsx)(h,{label:(0,B.jsxs)(`span`,{className:`flex items-center gap-2`,children:[n,t.cleared.has(e.attr)?(0,B.jsx)(b,{tone:`warn`,children:`will clear`}):a?(0,B.jsxs)(b,{tone:`up`,children:[(0,B.jsx)(y,{name:`lock`,className:`h-3 w-3`}),` saved`]}):null]}),hint:r,children:(0,B.jsxs)(`div`,{className:`flex gap-2`,children:[(0,B.jsx)(_,{value:i,onChange:n=>t.set(e.attr,n.target.value),placeholder:a?`•••••••• (leave blank to keep)`:`Not set`}),a&&(0,B.jsx)(C,{variant:`ghost`,size:`md`,onClick:()=>t.clearSecret(e.attr),title:`Remove saved secret on save`,children:`Clear`})]})})}return e.kind===`multiline`?(0,B.jsx)(h,{label:n,hint:r,children:(0,B.jsx)(d,{rows:3,value:i,onChange:n=>t.set(e.attr,n.target.value)})}):(0,B.jsx)(h,{label:n,hint:r,children:(0,B.jsx)(g,{type:e.kind===`int`||e.kind===`float`?`number`:`text`,step:e.kind===`float`?`any`:void 0,value:i,onChange:n=>t.set(e.attr,n.target.value)})})}function Ce({dirty:e,saving:t,onSave:n,onReset:r,extra:i}){return(0,B.jsxs)(`footer`,{className:`flex flex-wrap items-center justify-between gap-3 border-t border-line px-5 py-3`,children:[(0,B.jsxs)(`span`,{className:`flex items-center gap-2 text-xs text-muted`,children:[(0,B.jsx)(u,{tone:e?`warn`:`up`}),e?`Unsaved changes`:`Up to date`]}),(0,B.jsxs)(`div`,{className:`flex gap-2`,children:[i,(0,B.jsx)(C,{variant:`ghost`,size:`sm`,disabled:!e,onClick:r,children:`Reset`}),(0,B.jsx)(C,{size:`sm`,loading:t,disabled:!e,onClick:n,children:`Save`})]})]})}var we=P.flatMap(e=>e.fields);function $(e){return Object.assign({},...Object.values(e))}function Te(){let e=ye(we),{hydrate:t}=e,[n,i]=(0,M.useState)(!1),[a,s]=(0,M.useState)(null),[l,d]=(0,M.useState)(P[0].name),[f,m]=(0,M.useState)(!1),[h,g]=(0,M.useState)(!1),[_,S]=(0,M.useState)(null);(0,M.useEffect)(()=>{F().then(e=>{t($(e)),i(!0)}).catch(e=>s(r(e)))},[t]);function E(t){let n=P.find(e=>e.name===t);if(n.fields.some(t=>t.attr in e.payload))return`dirty`;let r=n.fields[0];return(r.kind===`password`?e.secretSet[r.attr]:(e.values[r.attr]??``)!==``)?`on`:`off`}async function D(){m(!0);try{e.hydrate($(await I(e.payload))),o.success(`Notification settings saved`)}catch(e){o.error(r(e))}finally{m(!1)}}async function O(){g(!0),S(null);try{let t=await L(e.payload);S(t),t.configured_channels.length||o.info(t.message??`No channel configured`)}catch(e){o.error(r(e))}finally{g(!1)}}if(a)return(0,B.jsx)(w,{title:`Could not load notification settings`,children:a});if(!n)return(0,B.jsx)(T,{className:`h-96 w-full`});let k=P.find(e=>e.name===l),A=P.filter(e=>E(e.name)===`on`).length;return(0,B.jsxs)(`div`,{className:`space-y-6`,children:[_&&_.configured_channels.length>0&&(0,B.jsxs)(v,{children:[(0,B.jsx)(x,{title:`Test delivery`,description:`Sent with your current (unsaved included) values`}),(0,B.jsx)(`div`,{className:`flex flex-wrap gap-2 p-5`,children:Object.entries(_.results).map(([e,t])=>(0,B.jsxs)(b,{tone:t?`up`:`down`,children:[(0,B.jsx)(y,{name:t?`check`:`x`,className:`h-3 w-3`}),` `,e]},e))})]}),(0,B.jsxs)(v,{className:`overflow-hidden`,children:[(0,B.jsxs)(`div`,{className:`grid md:grid-cols-[220px_minmax(0,1fr)]`,children:[(0,B.jsxs)(`nav`,{className:`border-line md:border-e`,children:[(0,B.jsxs)(`div`,{className:`px-4 py-3 text-xs text-muted`,children:[A,` of `,P.length,` channels active`]}),(0,B.jsx)(`ul`,{className:`flex gap-1 overflow-x-auto px-2 pb-2 md:block md:space-y-0.5 md:overflow-visible`,children:P.map(e=>{let t=E(e.name);return(0,B.jsx)(`li`,{className:`shrink-0`,children:(0,B.jsxs)(`button`,{type:`button`,onClick:()=>d(e.name),className:c(`flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-start text-sm`,e.name===l?`bg-raised text-fg`:`text-muted hover:text-fg`),children:[e.name,(0,B.jsx)(u,{tone:t===`on`?`up`:t===`dirty`?`warn`:`neutral`})]})},e.name)})})]}),(0,B.jsxs)(`div`,{className:`min-w-0`,children:[(0,B.jsx)(x,{title:k.name,description:E(k.name)===`on`?`Active - receives scheduled and manual run results.`:`Not configured - fill the fields below to enable.`,icon:`bell`}),(0,B.jsx)(p,{className:`grid gap-4 sm:grid-cols-2`,children:k.fields.map(t=>(0,B.jsx)(`div`,{className:t.kind===`multiline`||t.kind===`bool`?`sm:col-span-2`:void 0,children:(0,B.jsx)(Se,{spec:t,form:e})},t.attr))})]})]}),(0,B.jsx)(Ce,{dirty:e.dirty,saving:f,onSave:D,onReset:e.reset,extra:(0,B.jsx)(C,{variant:`secondary`,size:`sm`,icon:`send`,loading:h,onClick:O,children:`Send test`})})]})]})}export{ve as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,n,p as r}from"./format-d8InM0Zw.js";import{D as i}from"./ui-gsFb8B2m.js";import{R as a,d as o,i as s,r as c,yt as l}from"./LineChart-BaOkD1Ta.js";import{n as u,s as d,t as f}from"./BarChart-_yngarVl.js";import{y as p}from"./listings-BefgXpb1.js";var m=e(t(),1),h=r(),g=[`A candle's body runs from open to close; the thin wicks mark the day's high and low.`,`Breadth counts how many stocks rose versus fell. It can disagree with the index when a few giants carry it.`,`On a rotation chart, right means stronger than the index and up means that strength is rising.`,`NSE's normal trading session runs from 9:15 am to 3:30 pm IST, Monday to Friday.`,`A bulk deal is a single client trading more than 0.5% of a company's shares in one day.`,`Beta measures how much a stock tends to move for a 1% move in something else, like the market or crude.`,`The RBI repo rate is what the central bank charges banks for overnight money; it anchors loan rates.`,`A 52-week high or low is the highest or lowest price of the last year, a common reference for traders.`],_=[[62,54],[54,60],[60,46],[46,50],[50,38],[38,44],[44,30],[30,36],[36,24],[24,28],[28,16],[16,12]].map(([e,t],n)=>({x:16+n*19,o:e,c:t,h:Math.min(e,t)-4-n%3,l:Math.max(e,t)+3+n%2*2})),v=`M`+_.map(e=>`${e.x} ${(e.o+e.c)/2}`).join(` L`);function y({steps:e,className:t}){let[n,r]=(0,m.useState)(0),[a,o]=(0,m.useState)(()=>Math.floor(Math.random()*g.length));return(0,m.useEffect)(()=>{let t=window.setInterval(()=>r(t=>Math.min(t+1,e.length-1)),1400),n=window.setInterval(()=>o(e=>(e+1)%g.length),4500);return()=>{window.clearInterval(t),window.clearInterval(n)}},[e.length]),(0,h.jsxs)(`div`,{role:`status`,"aria-live":`polite`,className:i(`insight-loader relative flex flex-col items-center justify-center gap-4 overflow-hidden rounded-lg bg-canvas px-4 py-6 text-center`,t),children:[(0,h.jsxs)(`svg`,{viewBox:`0 0 240 80`,className:`h-28 w-full max-w-[380px]`,"aria-hidden":`true`,children:[[20,40,60].map(e=>(0,h.jsx)(`line`,{x1:`0`,x2:`240`,y1:e,y2:e,className:`stroke-line`,strokeOpacity:`0.5`,strokeDasharray:`2 4`},e)),_.map(({x:e,o:t,c:n,h:r,l:a},o)=>(0,h.jsxs)(`g`,{className:i(`insight-loader-candle`,n<t?`text-up`:`text-down`),style:{animationDelay:`${o*110}ms`,transformOrigin:`${e}px ${(t+n)/2}px`},children:[(0,h.jsx)(`line`,{x1:e,x2:e,y1:r,y2:a,stroke:`currentColor`,strokeWidth:`1.2`}),(0,h.jsx)(`rect`,{x:e-5,y:Math.min(t,n),width:`10`,height:Math.max(2,Math.abs(t-n)),rx:`1`,fill:`currentColor`})]},e)),(0,h.jsx)(`path`,{d:v,pathLength:1,fill:`none`,strokeWidth:`2`,strokeLinecap:`round`,className:`insight-loader-trend stroke-accent`}),(0,h.jsx)(`rect`,{x:`0`,y:`0`,width:`28`,height:`80`,className:`insight-loader-scan`})]}),(0,h.jsxs)(`div`,{className:`space-y-1`,children:[(0,h.jsxs)(`p`,{className:`insight-loader-fade text-sm font-medium`,children:[(0,h.jsx)(`span`,{className:`insight-loader-dot me-2 inline-block h-2 w-2 rounded-full bg-accent align-middle`}),e[n]]},n),(0,h.jsx)(`div`,{className:`mx-auto flex justify-center gap-1`,"aria-hidden":`true`,children:e.map((e,t)=>(0,h.jsx)(`span`,{className:i(`h-1 w-6 rounded-full transition-colors duration-500`,t<=n?`bg-accent`:`bg-raised`)},t))})]}),(0,h.jsxs)(`p`,{className:`insight-loader-fade max-w-md text-xs text-muted`,children:[(0,h.jsx)(`span`,{className:`font-medium text-accent-fg`,children:`Did you know? `}),g[a]]},a)]})}var b={consistent:{label:`Consistent`,className:`bg-up-soft text-up`,hint:`The best day landed within a few days of each other over 3, 5 and 10 years`},no_edge:{label:`No reliable edge`,className:`bg-raised text-muted`,hint:`The best day moved around between periods, so any day is about as good`},negligible:{label:`Gap too small`,className:`bg-raised text-muted`,hint:`Best and worst day differ by under 0.1 points a year, so the day makes no real difference`},short:{label:`Under 5 years`,className:`bg-warn-soft text-warn`,hint:`Only 3-5 years of prices, too short to check whether the day holds up`}};function x(e){return`${e}${e%100>=11&&e%100<=13?`th`:{1:`st`,2:`nd`,3:`rd`}[e%10]??`th`}`}function S({day:e,edge:t,spread:n}){if(!e||!t)return(0,h.jsx)(`span`,{className:`text-xs text-faint`,children:`—`});let r=b[t];return(0,h.jsxs)(`span`,{className:`inline-flex items-center justify-end gap-1.5 whitespace-nowrap text-xs`,title:`${r.hint}. Best beat worst by ${n?.toFixed(2)??`?`} points a year. Past behaviour, not advice.`,children:[(0,h.jsx)(`span`,{className:`tabular font-medium`,children:x(e)}),(0,h.jsx)(`span`,{className:i(`rounded px-1 text-[11px] font-medium`,r.className),children:t===`consistent`?`✓`:t===`short`?`<5y`:t===`negligible`?`~0`:`≈`})]})}function C({market:e,kind:t,symbol:r,highlight:g}){let[_,v]=(0,m.useState)(null),[S,C]=(0,m.useState)(null);(0,m.useEffect)(()=>{let i=!1;return v(null),C(null),p(e,t,r).then(e=>!i&&v(e)).catch(e=>!i&&C(n(e))),()=>{i=!0}},[e,t,r]);let w=_?.summary,T=(_?.curve??[]).filter(e=>e.xirr_pct!=null),E=T.length?T.reduce((e,t)=>t.xirr_pct>e.xirr_pct?t:e):null,D=T.length?T.reduce((e,t)=>t.xirr_pct<e.xirr_pct?t:e):null,O=D?D.xirr_pct:0,k=E?E.xirr_pct:0,A=Math.max((k-O)*.25,.02);return(0,h.jsxs)(`div`,{className:`rounded-lg border border-line p-4`,children:[(0,h.jsxs)(`div`,{className:`mb-3 flex flex-wrap items-start justify-between gap-2`,children:[(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`div`,{className:`text-sm font-semibold`,children:`Historically best SIP day`}),(0,h.jsx)(`div`,{className:`text-xs text-muted`,children:`A monthly SIP replayed on every day 1–28, ranked by XIRR`})]}),w&&(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`tabular text-2xl font-semibold`,children:x(w.best_day)}),(0,h.jsx)(`span`,{className:i(`rounded-md px-2 py-0.5 text-xs font-medium`,b[w.edge].className),title:b[w.edge].hint,children:b[w.edge].label})]})]}),S&&(0,h.jsx)(`p`,{className:`text-sm text-down`,children:S}),!_&&!S&&(0,h.jsx)(y,{className:`min-h-48`,steps:[`Downloading the full price history…`,`Replaying a SIP on every day 1–28…`,`Checking 3, 5 and 10 years…`]}),_&&!w&&(0,h.jsx)(`p`,{className:`text-sm text-muted`,children:_.note??`Not enough price history yet.`}),w&&(0,h.jsxs)(`div`,{className:`space-y-3`,children:[(0,h.jsxs)(`table`,{className:`tabular w-full whitespace-nowrap text-xs`,children:[(0,h.jsx)(`thead`,{className:`text-muted`,children:(0,h.jsxs)(`tr`,{children:[(0,h.jsx)(`th`,{className:`py-1 text-start font-medium`,children:`Period`}),(0,h.jsxs)(`th`,{className:`py-1 text-end font-medium`,children:[`Best`,(0,h.jsx)(`span`,{className:`hidden sm:inline`,children:` day`})]}),(0,h.jsxs)(`th`,{className:`py-1 text-end font-medium`,children:[`Worst`,(0,h.jsx)(`span`,{className:`hidden sm:inline`,children:` day`})]}),(0,h.jsxs)(`th`,{className:`py-1 text-end font-medium`,children:[(0,h.jsx)(`span`,{className:`hidden sm:inline`,children:`Best `}),`XIRR`]}),(0,h.jsx)(`th`,{className:`py-1 text-end font-medium`,title:`Best day's XIRR minus the worst day's, in points a year`,children:`Gap`})]})}),(0,h.jsx)(`tbody`,{className:`divide-y divide-line`,children:Object.entries(w.windows).map(([e,t])=>(0,h.jsxs)(`tr`,{children:[(0,h.jsx)(`td`,{className:`py-1.5 pe-2`,children:e.replace(`y`,` yrs`)}),(0,h.jsx)(`td`,{className:`py-1.5 text-end font-medium text-up`,children:x(t.best)}),(0,h.jsx)(`td`,{className:`py-1.5 text-end text-down`,children:x(t.worst)}),(0,h.jsxs)(`td`,{className:`py-1.5 text-end`,children:[t.best_xirr.toFixed(2),`%`]}),(0,h.jsxs)(`td`,{className:`py-1.5 text-end text-muted`,children:[t.spread.toFixed(2),` pts`]})]},e))})]}),T.length>0&&(0,h.jsxs)(`div`,{children:[(0,h.jsxs)(`div`,{className:`mb-1 text-xs text-muted`,children:[`XIRR by SIP day, last `,_.years,` years`]}),(0,h.jsx)(`div`,{className:`h-36`,children:(0,h.jsx)(l,{width:`100%`,height:`100%`,children:(0,h.jsxs)(f,{data:T,margin:{top:4,right:4,bottom:0,left:0},children:[(0,h.jsx)(s,{dataKey:`day`,tick:{fontSize:10},interval:2,tickLine:!1,axisLine:!1}),(0,h.jsx)(c,{domain:[O-A,k+A],tick:{fontSize:10},width:50,tickFormatter:e=>`${Number(e).toFixed(k-O<1?2:1)}%`,tickLine:!1,axisLine:!1}),(0,h.jsx)(a,{cursor:{fill:`var(--color-raised)`},contentStyle:{background:`var(--color-surface)`,border:`1px solid var(--color-line)`,borderRadius:8,fontSize:12},labelFormatter:e=>`SIP on the ${x(Number(e))}`,formatter:e=>[`${Number(e).toFixed(2)}% a year`,`XIRR`]}),g&&(0,h.jsx)(o,{x:g,stroke:`var(--color-accent)`,strokeDasharray:`3 3`}),(0,h.jsx)(u,{dataKey:`xirr_pct`,radius:[3,3,0,0],children:T.map(e=>(0,h.jsx)(d,{fill:e.day===E?.day?`var(--color-up)`:e.day===D?.day?`var(--color-down)`:`var(--color-line-strong)`},e.day))})]})})})]}),(0,h.jsxs)(`p`,{className:`text-xs text-faint`,children:[w.edge===`consistent`?`The ${x(w.best_day)} (or a day close to it) came out best over every period checked. `:w.edge===`negligible`?`Every day gave almost exactly the same return. `:w.edge===`no_edge`?`The best day changed from one period to the next, so it looks like chance. `:`Too little history to tell whether the best day holds up. `,`The gap between best and worst is `,w.spread.toFixed(2),` points a year over the longest period: pick the day that suits your salary. Buys on the first trading day on or after the chosen date`,t===`etf`?`; ETF prices adjusted for dividends and splits`:``,`. Past behaviour, as of `,w.as_of,`; not investment advice.`]})]})]})}export{y as i,C as n,x as r,S as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,c as n,p as r}from"./format-d8InM0Zw.js";import{D as i,b as a,f as o,l as s}from"./ui-gsFb8B2m.js";import{S as c}from"./listings-BefgXpb1.js";import{a as l,n as u}from"./options-BYAZnwzW.js";var d=e(t(),1),f=[[/\.(NS|BO)$/i,`india`],[/\.HK$/i,`hong_kong`],[/\.(SS|SZ)$/i,`china_a`],[/-USD$/i,`crypto`]];function p(e){let t=e.trim().toUpperCase();for(let[e,n]of f)if(e.test(t))return{symbol:n===`crypto`?t:t.replace(e,``),market:n};return null}function m(e,t){let n=e.trim().toUpperCase(),r=t.trim().toUpperCase();return n===r||/^\d+$/.test(n)&&/^\d+$/.test(r)&&Number(n)===Number(r)}function h(e,t,n){let r=t.filter(t=>m(t.symbol,e));if(r.length)return r.find(e=>e.market===n)??r[0]}var g=e=>e.trim().replace(/\s+/g,` `).toUpperCase();function _(e,t){let n=g(e),r=t.filter(e=>e.name&&g(e.name)===n);return r.length===1?r[0]:void 0}async function v(e,t,n){let r=e.trim().toUpperCase(),i=p(r);if(i)return i;try{let e=await n(r),i=h(r,e,t)??_(r,e);if(i)return{symbol:i.symbol,market:i.market}}catch{}return{symbol:r,market:t}}var y=r(),b={stock:`Stock`,etf:`ETF`,mf:`Fund`,crypto:`Crypto`};function x({value:e,onChange:t,onSelect:r,onSubmit:f,market:m=`all`,type:g=`all`,exclude:_=[],placeholder:v=`Search any stock, ETF or fund`,autoFocus:x,className:S,detect:C}){let[w,T]=(0,d.useState)([]),[E,D]=(0,d.useState)(!1),[O,k]=(0,d.useState)(!1),[A,j]=(0,d.useState)(-1),M=(0,d.useRef)(!1),N=(0,d.useId)(),P=C||m===`global`?`all`:m,F=(0,d.useRef)(C);F.current=C;let I=_.join(`,`);(0,d.useEffect)(()=>{let t=e.trim();if(M.current||t.length<1){M.current=!1,T([]),k(!1);return}let n=new AbortController;k(!0);let r=setTimeout(()=>{c(t,P,g,12,n.signal).then(e=>{let n=I?I.split(`,`):[];T(e.filter(e=>!n.includes(e.type))),j(-1);let r=F.current,i=r&&(p(t)??h(t,e,r.current));r&&i&&i.market!==r.current&&r.onDetect(i.market)}).catch(()=>{n.signal.aborted||T([])}).finally(()=>{n.signal.aborted||k(!1)})},180);return()=>{clearTimeout(r),n.abort()}},[e,P,g,I]);function L(e){M.current=!0,D(!1),T([]),r(e)}function R(e){e.key===`ArrowDown`&&w.length?(e.preventDefault(),D(!0),j(e=>(e+1)%w.length)):e.key===`ArrowUp`&&w.length?(e.preventDefault(),j(e=>e<=0?w.length-1:e-1)):e.key===`Enter`?E&&A>=0&&w[A]?(e.preventDefault(),L(w[A])):f&&(e.preventDefault(),D(!1),f()):e.key===`Escape`&&D(!1)}let z=E&&e.trim()!==``&&(w.length>0||!O);return(0,y.jsxs)(`div`,{className:i(`relative`,S),children:[(0,y.jsx)(s,{name:`search`,className:`pointer-events-none absolute top-1/2 start-3 h-4 w-4 -translate-y-1/2 text-faint`}),(0,y.jsx)(o,{value:e,onChange:e=>{t(e.target.value),D(!0)},onFocus:()=>D(!0),onBlur:()=>setTimeout(()=>D(!1),120),onKeyDown:R,placeholder:v,autoFocus:x,className:`ps-9`,role:`combobox`,"aria-expanded":z,"aria-controls":N,"aria-autocomplete":`list`,autoComplete:`off`,spellCheck:!1}),O&&(0,y.jsx)(a,{className:`absolute top-1/2 end-3 h-3.5 w-3.5 -translate-y-1/2 text-faint`}),z&&(0,y.jsx)(`ul`,{id:N,role:`listbox`,className:`absolute z-30 mt-1 max-h-80 w-full overflow-auto rounded-lg border border-line-strong bg-raised py-1 shadow-xl`,children:w.length===0?(0,y.jsxs)(`li`,{className:`px-3 py-2 text-xs text-muted`,children:[`No listing matches. `,f?`Press Enter to use the typed symbol as-is.`:``]}):w.map((e,t)=>(0,y.jsxs)(`li`,{role:`option`,"aria-selected":t===A,onMouseDown:t=>{t.preventDefault(),L(e)},onMouseEnter:()=>j(t),className:i(`flex cursor-pointer items-center gap-3 px-3 py-2`,t===A&&`bg-line`),children:[(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,y.jsx)(`span`,{className:`font-mono text-xs font-semibold`,children:e.symbol}),(0,y.jsxs)(`span`,{className:`rounded bg-canvas px-1.5 text-[12px] text-muted`,children:[l(u,e.market),` · `,b[e.type]??e.type]})]}),(0,y.jsx)(`div`,{className:`truncate text-xs text-muted`,children:e.name})]}),(0,y.jsx)(`span`,{className:`tabular shrink-0 text-xs text-muted`,children:n(e.price,e.currency)})]},`${e.market}:${e.type}:${e.symbol}`))})]})}export{v as n,x as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/TradeChart-ZjsycacC.js","assets/rolldown-runtime-XKyaHtl9.js","assets/format-d8InM0Zw.js","assets/preload-helper-BLdHbfdN.js","assets/index-CKAnq-Or.js","assets/toast-DDradTZw.js","assets/ui-gsFb8B2m.js","assets/files-CpgiZRbN.js","assets/index-D4U8E6LH.css","assets/lightweight-charts.production-BF2noug5.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{n as e,r as t}from"./rolldown-runtime-XKyaHtl9.js";import{b as n,c as r,l as i,n as a,o,p as s,s as c,t as l,u}from"./format-d8InM0Zw.js";import{t as d}from"./preload-helper-BLdHbfdN.js";import{t as f}from"./toast-DDradTZw.js";import{C as p,D as m,S as h,_ as g,a as _,c as v,f as y,g as b,i as x,l as S,n as C,o as w,p as T,r as E,s as D,t as O,w as k,y as A}from"./ui-gsFb8B2m.js";import{j,u as M}from"./index-CKAnq-Or.js";import{m as N,t as P}from"./AreaChart-2i67V6Jf.js";import{R as F,a as I,d as L,i as R,pt as z,r as B,t as V,u as H,yt as U}from"./LineChart-BaOkD1Ta.js";import{n as W,r as ee,t as te}from"./BarChart-_yngarVl.js";import{S as G}from"./listings-BefgXpb1.js";import{A as K,C as q,D as ne,E as re,O as ie,S as J,T as ae,_ as oe,a as se,b as ce,c as le,d as ue,f as de,g as fe,h as pe,i as me,k as he,l as ge,m as _e,n as ve,o as ye,p as be,r as xe,s as Se,t as Ce,u as we,v as Te,w as Ee,x as De,y as Oe}from"./trade-fndw1Ql3.js";import{a as ke,n as Ae}from"./options-BYAZnwzW.js";import{n as je,t as Me}from"./SymbolSearch-CBOVPEk1.js";import{t as Ne}from"./ExportMenu-DaZ1xVmW.js";var Y=t(n(),1),X=s(),Pe={vwap:`#f5b942`,ema9:`#6d8cff`,ema21:`#c77dff`,ema50:`#22d3ee`,ema200:`#f472b6`,vwma13:`#38bdf8`,vwma19:`#fbbf24`},Z={india:`INR`,us:`USD`,china_a:`CNY`,hong_kong:`HKD`,crypto:`USD`,global:`USD`},Fe={pct_up:`3`,pct_down:`3`,rsi_above:`70`,rsi_below:`30`,volume_spike:`2`,high_breakout:`20`,low_breakdown:`20`},Ie={price:`Price`,"%":`Percent move today`,rsi:`RSI level (0–100)`,"x avg":`Multiple of the 20-day average volume`,days:`Look-back in trading days`},Le={active:`up`,paused:`neutral`,triggered:`accent`,expired:`neutral`};function Re({symbol:e,market:t,alerts:n,onChanged:r}){let[s,c]=(0,Y.useState)([]),[l,d]=(0,Y.useState)([]),[p,b]=(0,Y.useState)(null),[T,O]=(0,Y.useState)(!1),[k,A]=(0,Y.useState)({symbol:e,market:t,search:e,kind:`price_above`,value:``,note:``,repeat:!1,cooldown:`30`}),[j,M]=(0,Y.useState)(!1);(0,Y.useEffect)(()=>{le().then(c).catch(()=>c([])),ge().then(b).catch(()=>b(null))},[]);function N(){De(30).then(d).catch(()=>d([]))}(0,Y.useEffect)(N,[n]),(0,Y.useEffect)(()=>{A(n=>({...n,symbol:e,market:t,search:e}))},[e,t]);let P=s.find(e=>e.kind===k.kind);async function F(){let e=parseFloat(k.value);if(k.symbol&&Number.isFinite(e)){M(!0);try{await xe({symbol:k.symbol,market:k.market,kind:k.kind,value:e,note:k.note,repeat:k.repeat,cooldown_minutes:parseInt(k.cooldown,10)||0}),f.success(`Alert created`),A(e=>({...e,value:Fe[e.kind]??``,note:``})),r()}catch(e){f.error(a(e))}finally{M(!1)}}}async function I(e,t){try{await e(),t&&f.success(t),r()}catch(e){f.error(a(e))}}async function L(){O(!0);try{let e=await ve();f[e.fired.length?`success`:`info`](e.fired.length?`${e.fired.length} alert(s) fired: ${e.fired.map(e=>e.symbol).join(`, `)}`:`Checked ${e.checked} alert(s); none fired`),r()}catch(e){f.error(a(e))}finally{O(!1)}}let R=[[`Active`,(n??[]).filter(e=>e.status===`active`)],[`Paused`,(n??[]).filter(e=>e.status===`paused`)],[`Fired / expired`,(n??[]).filter(e=>e.status===`triggered`||e.status===`expired`)]];return(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[360px_minmax(0,1fr)]`,children:[(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`New alert`,icon:`bell`}),(0,X.jsxs)(_,{className:`space-y-4`,children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-[minmax(0,1fr)_120px] gap-2`,children:[(0,X.jsx)(v,{label:`Symbol`,children:(0,X.jsx)(Me,{value:k.search,onChange:e=>A(t=>({...t,search:e,symbol:e.trim().toUpperCase()})),onSelect:e=>A(t=>({...t,symbol:e.symbol,market:e.market,search:e.symbol})),market:k.market,placeholder:`RELIANCE, AAPL…`})}),(0,X.jsx)(v,{label:`Market`,children:(0,X.jsx)(g,{options:Ae,value:k.market,onChange:e=>A(t=>({...t,market:e.target.value}))})})]}),(0,X.jsx)(v,{label:`Condition`,children:(0,X.jsx)(g,{options:s.map(e=>({value:e.kind,label:e.label})),value:k.kind,onChange:e=>{let t=e.target.value;A(e=>({...e,kind:t,value:Fe[t]??``}))}})}),(0,X.jsx)(v,{label:P?Ie[P.unit]:`Value`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:k.value,onChange:e=>A(t=>({...t,value:e.target.value})),onKeyDown:e=>e.key===`Enter`&&F()})}),(0,X.jsx)(v,{label:`Note (sent with the alert)`,children:(0,X.jsx)(y,{value:k.note,onChange:e=>A(t=>({...t,note:e.target.value})),placeholder:`e.g. breakout entry, trail stop`})}),(0,X.jsxs)(`label`,{className:`flex cursor-pointer items-start gap-3`,children:[(0,X.jsx)(`input`,{type:`checkbox`,checked:k.repeat,onChange:e=>A(t=>({...t,repeat:e.target.checked})),className:`mt-0.5 h-4 w-4 accent-[var(--color-accent)]`}),(0,X.jsxs)(`span`,{children:[(0,X.jsx)(`span`,{className:`block text-sm font-medium`,children:`Repeat`}),(0,X.jsx)(`span`,{className:`block text-xs text-muted`,children:`Fire again each time the condition becomes true after clearing. Off = fire once.`})]})]}),k.repeat&&(0,X.jsx)(v,{label:`Minimum minutes between alerts`,children:(0,X.jsx)(y,{type:`number`,min:`0`,value:k.cooldown,onChange:e=>A(t=>({...t,cooldown:e.target.value})),className:`w-28`})}),(0,X.jsx)(E,{onClick:F,loading:j,disabled:!k.symbol||!k.value,icon:`plus`,children:`Create alert`})]})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Monitor`}),(0,X.jsxs)(_,{className:`space-y-3 text-xs text-muted`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-fg`,children:[(0,X.jsx)(h,{tone:p?.running?`up`:`down`}),p?.running?`Checking every ${p.poll_seconds}s while each market is open`:`Not running (start the API server)`]}),(0,X.jsxs)(`p`,{children:[`Alerts go to the channels routed for `,(0,X.jsx)(`b`,{className:`text-fg`,children:`alerts`}),` under Settings → Notifications (Telegram, push, …). Crypto is checked around the clock.`]}),(0,X.jsx)(E,{size:`sm`,variant:`secondary`,icon:`refresh`,loading:T,onClick:L,children:`Check now (ignores market hours)`})]})]})]}),(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Your alerts`,description:n?`${n.length} total`:void 0}),n&&n.length===0?(0,X.jsx)(D,{icon:`bell`,title:`No alerts yet`,description:`Create one here or click a price on the chart.`}):R.filter(([,e])=>e.length).map(([e,t])=>(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`border-t border-line bg-canvas/40 px-5 py-1.5 text-xs font-medium text-muted`,children:e}),(0,X.jsx)(`ul`,{className:`divide-y divide-line`,children:t.map(e=>(0,X.jsxs)(`li`,{className:`flex flex-wrap items-center gap-x-4 gap-y-1 px-5 py-2.5 text-sm`,children:[(0,X.jsx)(`span`,{className:`w-24 font-mono font-medium`,children:e.symbol}),(0,X.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,X.jsx)(`span`,{className:`block`,children:e.description}),(0,X.jsxs)(`span`,{className:`block text-xs text-muted`,children:[e.note&&`${e.note} · `,e.repeat?`repeats`:`once`,e.last_value!=null&&` · now ${o(e.last_value)}`,e.last_triggered_at&&` · fired ${i(e.last_triggered_at)}`,e.trigger_count>1&&` (${e.trigger_count}×)`]})]}),(0,X.jsx)(C,{tone:Le[e.status],children:e.status}),(0,X.jsxs)(`div`,{className:`flex gap-1`,children:[e.status===`active`?(0,X.jsx)(E,{size:`sm`,variant:`ghost`,onClick:()=>I(()=>ie(e.id,{status:`paused`})),children:`Pause`}):(0,X.jsx)(E,{size:`sm`,variant:`ghost`,onClick:()=>I(()=>ie(e.id,{status:`active`}),`Alert armed`),children:e.status===`paused`?`Resume`:`Re-arm`}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>I(()=>me(e.id)),className:`rounded-md p-1.5 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Delete alert for ${e.symbol}`,children:(0,X.jsx)(S,{name:`trash`})})]})]},e.id))})]},e))]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Recent triggers`}),l.length===0?(0,X.jsx)(_,{children:(0,X.jsx)(`p`,{className:`text-xs text-muted`,children:`Fired alerts appear here with where they were sent.`})}):(0,X.jsx)(`ul`,{className:`divide-y divide-line`,children:l.map(e=>{let t=Object.entries(e.delivery??{});return(0,X.jsxs)(`li`,{className:`px-5 py-2.5 text-sm`,children:[(0,X.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,X.jsx)(`span`,{className:`font-mono font-medium`,children:e.symbol}),(0,X.jsx)(`span`,{className:`text-xs text-muted`,children:u(e.created_at).toLocaleString()})]}),(0,X.jsx)(`pre`,{className:`mt-1 font-sans text-xs whitespace-pre-wrap text-muted`,children:e.message}),(0,X.jsx)(`div`,{className:`mt-1 flex flex-wrap gap-2 text-[12px]`,children:t.length===0?(0,X.jsx)(`span`,{className:`text-warn`,children:`No alert channel configured`}):t.map(([e,t])=>(0,X.jsxs)(`span`,{className:m(t?`text-up`:`text-down`),children:[t?`✓`:`✗`,` `,e]},e))})]},e.id)})})]})]})]})}function Q({label:e,value:t,sub:n,tone:r}){return(0,X.jsxs)(`div`,{className:`bg-surface px-4 py-3`,children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:e}),(0,X.jsx)(`div`,{className:m(`tabular text-sm font-semibold`,r===`up`&&`text-up`,r===`down`&&`text-down`),children:t}),n&&(0,X.jsx)(`div`,{className:`text-[12px] text-faint`,children:n})]})}var ze=[{value:`1y`,label:`1 year`},{value:`2y`,label:`2 years`},{value:`5y`,label:`5 years`},{value:`10y`,label:`10 years`},{value:`max`,label:`All history`}],Be={fast:`Fast average (bars)`,slow:`Slow average (bars)`,entry_days:`Entry: N-bar high`,exit_days:`Exit: M-bar low`,buy_below:`Buy when RSI below`,sell_above:`Exit when RSI above`,period:`Period`,multiplier:`ATR multiplier`,min_score:`Min model lean (-1 to 1)`,k:`Neighbours (k)`,horizon:`Model looks ahead (bars)`,min_vote:`Min neighbour vote`,use_filter:`Use the kNN filter (1 = yes, 0 = no)`};function Ve({symbol:e,market:t}){let[n,i]=(0,Y.useState)([]),[s,l]=(0,Y.useState)({symbol:e,market:t,interval:`1d`,period:`5y`,strategy:`ema_cross`,params:{},capital:1e5,sizing:`percent`,position_pct:100,risk_pct:1,stop_type:`atr`,stop_value:2,target_r:null,cost_pct:t===`india`?.12:.05,slippage_pct:.05,allow_short:!1,optimize:!1,objective:`sharpe`}),[u,d]=(0,Y.useState)(null),[h,S]=(0,Y.useState)(!1);(0,Y.useEffect)(()=>{Oe().then(i).catch(()=>i([]))},[]),(0,Y.useEffect)(()=>{l(n=>({...n,symbol:e,market:t})),d(null)},[e,t]);let C=n.find(e=>e.id===s.strategy),T=e=>l(t=>({...t,...e})),k=Z[t];async function A(){S(!0);try{let e=await Ee(s);d(e),s.optimize&&e.optimization&&T({params:e.optimization.best})}catch(e){f.error(a(e))}finally{S(!1)}}let j=u?.metrics,M=u?.split,N=M&&M.train.total_return>0&&(M.test.total_return<0||(M.test.sharpe??0)<(M.train.sharpe??0)/2);return(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[360px_minmax(0,1fr)]`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Strategy test`,description:`${e} · signals on close, filled at the next open`}),(0,X.jsxs)(_,{className:`space-y-4`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,X.jsx)(b,{options:[{value:`1d`,label:`Daily`},{value:`1wk`,label:`Weekly`},{value:`1h`,label:`Hourly`}],value:s.interval,onChange:e=>T({interval:e}),size:`sm`}),(0,X.jsx)(g,{className:`w-36`,options:ze,value:s.period,onChange:e=>T({period:e.target.value})})]}),s.interval===`1h`&&(0,X.jsx)(`p`,{className:`text-[12px] text-muted`,children:`Hourly history is limited to the last 2 years.`}),(0,X.jsx)(v,{label:`Strategy`,hint:C?.description,children:(0,X.jsx)(g,{options:n.map(e=>({value:e.id,label:e.label})),value:s.strategy,onChange:e=>T({strategy:e.target.value,params:{}})})}),C&&(0,X.jsx)(`div`,{className:`grid grid-cols-2 gap-2`,children:Object.entries(C.params).map(([e,t])=>(0,X.jsx)(v,{label:Be[e]??e,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:s.params[e]??t,onChange:t=>T({params:{...s.params,[e]:parseFloat(t.target.value)}})})},e))}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,X.jsx)(v,{label:`Capital (${k})`,children:(0,X.jsx)(y,{type:`number`,value:s.capital,onChange:e=>T({capital:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Sizing`,children:(0,X.jsx)(g,{options:[{value:`percent`,label:`% of equity`},{value:`risk`,label:`Risk % at stop`}],value:s.sizing,onChange:e=>T({sizing:e.target.value})})}),s.sizing===`percent`?(0,X.jsx)(v,{label:`Position % of equity`,children:(0,X.jsx)(y,{type:`number`,value:s.position_pct,onChange:e=>T({position_pct:parseFloat(e.target.value)||0})})}):(0,X.jsx)(v,{label:`Risk % per trade`,children:(0,X.jsx)(y,{type:`number`,step:`0.1`,value:s.risk_pct,onChange:e=>T({risk_pct:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Stop loss`,children:(0,X.jsx)(g,{options:[{value:`none`,label:`None`},{value:`percent`,label:`% below entry`},{value:`atr`,label:`ATR multiple`}],value:s.stop_type,onChange:e=>T({stop_type:e.target.value})})}),s.stop_type!==`none`&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(v,{label:s.stop_type===`atr`?`ATR ×`:`Stop %`,children:(0,X.jsx)(y,{type:`number`,step:`0.1`,value:s.stop_value,onChange:e=>T({stop_value:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Target (R, optional)`,children:(0,X.jsx)(y,{type:`number`,step:`0.5`,value:s.target_r??``,onChange:e=>T({target_r:e.target.value?parseFloat(e.target.value):null})})})]}),(0,X.jsx)(v,{label:`Costs % per side`,children:(0,X.jsx)(y,{type:`number`,step:`0.01`,value:s.cost_pct,onChange:e=>T({cost_pct:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Slippage % per side`,children:(0,X.jsx)(y,{type:`number`,step:`0.01`,value:s.slippage_pct,onChange:e=>T({slippage_pct:parseFloat(e.target.value)||0})})})]}),s.sizing===`risk`&&s.stop_type===`none`&&(0,X.jsx)(`p`,{className:`text-xs text-warn`,children:`Risk sizing needs a stop; without one, % of equity is used.`}),(0,X.jsx)(p,{checked:s.allow_short,onChange:e=>T({allow_short:e}),label:`Also trade short`,description:`Exit signals open a short position.`}),(0,X.jsxs)(`div`,{className:`rounded-lg border border-line p-3`,children:[(0,X.jsx)(p,{checked:s.optimize,onChange:e=>T({optimize:e}),label:`Optimise parameters`,description:`Grid-search on the first 70% of history only, then judge the winner on the unseen last 30%.`}),s.optimize&&(0,X.jsx)(v,{label:`Optimise for`,className:`mt-3`,children:(0,X.jsx)(g,{options:[{value:`sharpe`,label:`Sharpe ratio (risk-adjusted)`},{value:`total_return`,label:`Total return`},{value:`cagr`,label:`CAGR`},{value:`profit_factor`,label:`Profit factor`}],value:s.objective,onChange:e=>T({objective:e.target.value})})})]}),(0,X.jsx)(E,{onClick:A,loading:h,icon:`play`,className:`w-full`,children:h?`Testing…`:`Run backtest`}),(0,X.jsx)(`p`,{className:`text-[12px] text-faint`,children:`Past results don't predict future ones. Costs default to Indian delivery charges (~0.12% a side); change them for your broker.`})]})]}),!u||!j?(0,X.jsx)(x,{children:(0,X.jsx)(D,{icon:`analyze`,title:`No backtest yet`,description:`Choose a strategy and run it on this stock's history.`})}):(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-line bg-line sm:grid-cols-4`,children:[(0,X.jsx)(Q,{label:`Total return`,value:c(j.total_return),tone:j.total_return>=0?`up`:`down`,sub:`buy & hold ${c(j.buy_hold_return)}`}),(0,X.jsx)(Q,{label:`CAGR`,value:c(j.cagr)}),(0,X.jsx)(Q,{label:`Max drawdown`,value:c(j.max_drawdown),tone:`down`}),(0,X.jsx)(Q,{label:`Sharpe`,value:o(j.sharpe)}),(0,X.jsx)(Q,{label:`Trades`,value:String(j.trades),sub:`avg ${o(j.avg_bars,0)} bars held`}),(0,X.jsx)(Q,{label:`Win rate`,value:j.win_rate==null?`—`:`${j.win_rate}%`}),(0,X.jsx)(Q,{label:`Profit factor`,value:o(j.profit_factor),sub:j.avg_r==null?void 0:`avg ${j.avg_r}R`}),(0,X.jsx)(Q,{label:`Time in market`,value:j.exposure==null?`—`:`${j.exposure}%`,sub:`final ${r(j.final_equity,k)}`})]}),j.trades<10&&(0,X.jsxs)(O,{tone:`warn`,title:`Few trades`,children:[j.trades,` trades is too small a sample to trust. Use a longer period or a faster strategy.`]}),N&&(0,X.jsx)(O,{tone:`warn`,title:`Looks overfit`,children:`It did well on the first 70% of history but not on the last 30%. The edge may not be real.`}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Equity vs buy & hold`,description:`${new Date(j.start).toLocaleDateString()} – ${new Date(j.end).toLocaleDateString()} · ${j.bars} bars · params ${Object.entries(u.params).map(([e,t])=>`${e}=${t}`).join(`, `)}`}),(0,X.jsxs)(_,{className:`space-y-2`,children:[(0,X.jsx)(`div`,{className:`h-64`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(V,{data:u.equity,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`time`,tickFormatter:e=>new Date(e).toLocaleDateString(void 0,{month:`short`,year:`2-digit`}),tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,minTickGap:40}),(0,X.jsx)(B,{orientation:`right`,width:64,tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,domain:[`auto`,`auto`]}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},labelFormatter:e=>new Date(String(e)).toLocaleDateString(),formatter:(e,t)=>[r(Number(e),k),t===`equity`?`Strategy`:`Buy & hold`]}),(0,X.jsx)(z,{formatter:e=>e===`equity`?`Strategy`:`Buy & hold`,wrapperStyle:{fontSize:12}}),(0,X.jsx)(I,{type:`monotone`,dataKey:`equity`,stroke:`var(--color-accent)`,dot:!1,strokeWidth:1.75}),(0,X.jsx)(I,{type:`monotone`,dataKey:`buy_hold`,stroke:`var(--color-faint)`,dot:!1,strokeWidth:1,strokeDasharray:`4 3`})]})})}),(0,X.jsx)(`div`,{className:`h-24`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(P,{data:u.equity,margin:{top:0,right:4,bottom:0,left:0},children:[(0,X.jsx)(R,{dataKey:`time`,hide:!0}),(0,X.jsx)(B,{orientation:`right`,width:64,tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,tickFormatter:e=>`${e}%`}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},labelFormatter:e=>new Date(String(e)).toLocaleDateString(),formatter:e=>[`${e}%`,`Drawdown`]}),(0,X.jsx)(ee,{type:`monotone`,dataKey:`drawdown`,stroke:`var(--color-down)`,fill:`var(--color-down)`,fillOpacity:.15,strokeWidth:1})]})})})]})]}),M&&(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Out-of-sample check`,description:`Same settings on the first 70% of history vs the last 30%.`}),(0,X.jsx)(He,{train:M.train,test:M.test})]}),u.optimization&&(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Optimisation`,description:`Best on the training part by ${u.optimization.objective}: ${Object.entries(u.optimization.best).map(([e,t])=>`${e}=${t}`).join(`, `)} · on unseen data: ${c(u.optimization.test.total_return)} return, Sharpe ${o(u.optimization.test.sharpe)}`}),(0,X.jsx)(`div`,{className:`max-h-72 overflow-auto`,children:(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`sticky top-0 border-y border-line bg-surface text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Parameters`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Return`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Sharpe`}),(0,X.jsx)(`th`,{className:`px-4 py-2 text-end font-medium`,children:`Trades`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:[...u.optimization.grid].sort((e,t)=>(t.score??-1e9)-(e.score??-1e9)).map(e=>{let t=JSON.stringify(e.params)===JSON.stringify(u.optimization.best);return(0,X.jsxs)(`tr`,{className:m(t&&`bg-accent-soft/50`),children:[(0,X.jsx)(`td`,{className:`px-4 py-1.5 font-mono text-xs`,children:Object.entries(e.params).map(([e,t])=>`${e}=${t}`).join(` `)}),(0,X.jsx)(`td`,{className:m(`tabular px-3 py-1.5 text-end`,e.total_return>=0?`text-up`:`text-down`),children:c(e.total_return)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-1.5 text-end`,children:o(e.sharpe)}),(0,X.jsx)(`td`,{className:`tabular px-4 py-1.5 text-end`,children:e.trades})]},JSON.stringify(e.params))})})]})})]}),(0,X.jsxs)(x,{className:`overflow-hidden`,children:[(0,X.jsx)(w,{title:`Trades`,description:`${u.trades.length} total`}),(0,X.jsx)(`div`,{className:`max-h-96 overflow-auto`,children:(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`sticky top-0 border-y border-line bg-surface text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Entry`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-start font-medium`,children:`Exit`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Prices`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Return`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`P&L`}),(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Exit reason`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:[...u.trades].reverse().map((e,t)=>(0,X.jsxs)(`tr`,{children:[(0,X.jsxs)(`td`,{className:`px-4 py-1.5 text-xs whitespace-nowrap`,children:[(0,X.jsx)(`span`,{className:m(`me-1.5 font-medium uppercase`,e.side===`long`?`text-up`:`text-down`),children:e.side}),new Date(e.entry_time).toLocaleDateString()]}),(0,X.jsx)(`td`,{className:`px-3 py-1.5 text-xs whitespace-nowrap text-muted`,children:new Date(e.exit_time).toLocaleDateString()}),(0,X.jsxs)(`td`,{className:`tabular px-3 py-1.5 text-end text-xs whitespace-nowrap`,children:[o(e.entry),` → `,o(e.exit)]}),(0,X.jsx)(`td`,{className:m(`tabular px-3 py-1.5 text-end`,e.return_pct>=0?`text-up`:`text-down`),children:c(e.return_pct)}),(0,X.jsx)(`td`,{className:m(`tabular px-3 py-1.5 text-end`,e.pnl>=0?`text-up`:`text-down`),children:r(e.pnl,k)}),(0,X.jsxs)(`td`,{className:`px-4 py-1.5 text-xs text-muted`,children:[e.reason,e.r!=null&&` · ${e.r}R`]})]},t))})]})})]})]})]})}function He({train:e,test:t}){return(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`border-y border-line text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`First 70% (in-sample)`}),(0,X.jsx)(`th`,{className:`px-4 py-2 text-end font-medium`,children:`Last 30% (unseen)`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:[[`Period`,e=>`${new Date(e.start).toLocaleDateString()} – ${new Date(e.end).toLocaleDateString()}`],[`Return`,e=>c(e.total_return)],[`Buy & hold`,e=>c(e.buy_hold_return)],[`Max drawdown`,e=>c(e.max_drawdown)],[`Sharpe`,e=>o(e.sharpe)],[`Trades`,e=>String(e.trades)],[`Win rate`,e=>e.win_rate==null?`—`:`${e.win_rate}%`]].map(([n,r])=>(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`td`,{className:`px-4 py-1.5 text-muted`,children:n}),(0,X.jsx)(`td`,{className:`tabular px-3 py-1.5 text-end`,children:r(e)}),(0,X.jsx)(`td`,{className:`tabular px-4 py-1.5 text-end`,children:r(t)})]},n))})]})}var Ue=[`NIFTY`,`BANKNIFTY`,`FINNIFTY`,`MIDCPNIFTY`,`NIFTYNXT50`],We=12,Ge=[{value:`long_call`,label:`Long call`},{value:`long_put`,label:`Long put`},{value:`bull_call`,label:`Bull call spread`},{value:`bear_put`,label:`Bear put spread`},{value:`straddle`,label:`Long straddle`},{value:`strangle`,label:`Long strangle`},{value:`iron_condor`,label:`Short iron condor`},{value:`covered_call`,label:`Covered call`}];function Ke({symbol:e,market:t}){let[n,i]=(0,Y.useState)(t===`us`||t===`global`?`us`:`india`),[s,c]=(0,Y.useState)(t===`india`||t===`us`||t===`global`?e:`NIFTY`),[u,d]=(0,Y.useState)(s),[p,h]=(0,Y.useState)(),[C,T]=(0,Y.useState)(null),[k,j]=(0,Y.useState)(null),[M,N]=(0,Y.useState)(!1),[P,ee]=(0,Y.useState)(`1`),[G,K]=(0,Y.useState)([]),[q,ne]=(0,Y.useState)(null),[re,ie]=(0,Y.useState)(`oi`);(0,Y.useEffect)(()=>{T(null),j(null),_e(s,n,p).then(e=>{T(e),e.lot_size&&ee(String(e.lot_size))}).catch(e=>j(a(e)))},[s,n,p]),(0,Y.useEffect)(()=>K([]),[s,p]);let J=C?.summary,ae=Z[n],oe=(0,Y.useMemo)(()=>{if(!C||!J?.atm_strike)return C?.rows??[];if(M)return C.rows;let e=C.rows.findIndex(e=>e.strike===J.atm_strike);return C.rows.slice(Math.max(0,e-We),e+We+1)},[C,J,M]);(0,Y.useEffect)(()=>{if(!G.length||!J?.spot){ne(null);return}let e=window.setTimeout(()=>{fe({legs:G,spot:J.spot,days:J.days_to_expiry,market:n}).then(ne).catch(e=>f.error(a(e)))},250);return()=>window.clearTimeout(e)},[G,J,n]);let se=Math.max(1,parseFloat(P)||1);function ce(e,t,n){let r=e[t];r?.ltp&&K(i=>[...i,{type:t,side:n,strike:e.strike,premium:r.ltp,quantity:se,iv:r.iv}])}function le(e){if(!C||!J?.atm_strike)return;let t=C.rows.findIndex(e=>e.strike===J.atm_strike),n=e=>C.rows[Math.min(C.rows.length-1,Math.max(0,t+e))],r=(e,t,n)=>({type:t,side:n,strike:e.strike,premium:e[t]?.ltp??0,quantity:se,iv:e[t]?.iv}),i=n(0),a={long_call:[r(i,`call`,`buy`)],long_put:[r(i,`put`,`buy`)],bull_call:[r(i,`call`,`buy`),r(n(3),`call`,`sell`)],bear_put:[r(i,`put`,`buy`),r(n(-3),`put`,`sell`)],straddle:[r(i,`call`,`buy`),r(i,`put`,`buy`)],strangle:[r(n(2),`call`,`buy`),r(n(-2),`put`,`buy`)],iron_condor:[r(n(-4),`put`,`buy`),r(n(-2),`put`,`sell`),r(n(2),`call`,`sell`),r(n(4),`call`,`buy`)],covered_call:[{type:`stock`,side:`buy`,strike:0,premium:J.spot,quantity:se},r(n(2),`call`,`sell`)]};K(a[e])}let ue=oe.map(e=>({strike:e.strike,call:re===`oi`?e.call?.oi??0:e.call?.chg_oi??0,put:re===`oi`?e.put?.oi??0:e.put?.chg_oi??0}));return(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3`,children:[(0,X.jsx)(b,{options:[{value:`india`,label:`India (NSE)`},{value:`us`,label:`US`}],value:n,onChange:e=>{let t=e,n=t===`india`?`NIFTY`:`SPY`;i(t),h(void 0),d(n),c(n)},size:`sm`}),(0,X.jsxs)(`div`,{className:`flex gap-2`,children:[(0,X.jsx)(y,{value:u,onChange:e=>d(e.target.value.toUpperCase()),onKeyDown:e=>e.key===`Enter`&&u.trim()&&(h(void 0),c(u.trim())),className:`w-40`,placeholder:n===`india`?`NIFTY, RELIANCE`:`AAPL, SPY`}),(0,X.jsx)(E,{variant:`secondary`,onClick:()=>u.trim()&&(h(void 0),c(u.trim())),children:`Load`})]}),n===`india`&&(0,X.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:Ue.map(e=>(0,X.jsx)(`button`,{type:`button`,onClick:()=>{d(e),h(void 0),c(e)},className:m(`rounded-full border px-2.5 py-0.5 text-xs font-medium`,s===e?`border-accent bg-accent-soft text-fg`:`border-line text-muted hover:text-fg`),children:e},e))}),C&&(0,X.jsx)(g,{className:`w-40`,options:C.expiries.map(e=>({value:e,label:e})),value:J?.expiry??``,onChange:e=>h(e.target.value)}),(0,X.jsxs)(`span`,{className:`text-xs text-muted`,children:[n===`india`?`NSE option chain`:`US option chain (market data feed)`,C?.timestamp&&` · ${C.timestamp}`]})]}),k?(0,X.jsxs)(O,{tone:`warn`,title:`Option chain unavailable`,children:[k,` `,`Options are available for NSE indices and F&O stocks, and for US listed symbols.`]}):!C||!J?(0,X.jsx)(A,{className:`h-96 w-full`}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-line bg-line sm:grid-cols-4 lg:grid-cols-8`,children:[(0,X.jsx)($,{label:`Spot`,value:r(J.spot,ae)}),(0,X.jsx)($,{label:`Days to expiry`,value:String(J.days_to_expiry)}),(0,X.jsx)($,{label:`ATM IV`,value:J.atm_iv==null?`—`:`${J.atm_iv}%`}),(0,X.jsx)($,{label:`Expected move`,value:J.expected_move==null?`—`:`±${o(J.expected_move)}`,sub:`1 sd to expiry`}),(0,X.jsx)($,{label:`PCR (OI)`,value:o(J.pcr_oi),sub:J.pcr_oi==null?void 0:J.pcr_oi>1.2?`put-heavy`:J.pcr_oi<.7?`call-heavy`:`balanced`}),(0,X.jsx)($,{label:`Max pain`,value:J.max_pain==null?`—`:o(J.max_pain,0)}),(0,X.jsx)($,{label:`Support (put OI)`,value:J.support==null?`—`:o(J.support,0),tone:`up`}),(0,X.jsx)($,{label:`Resistance (call OI)`,value:J.resistance==null?`—`:o(J.resistance,0),tone:`down`})]}),C.vol_compare&&(0,X.jsx)(Ye,{v:C.vol_compare}),(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-2`,children:[C.gex&&(0,X.jsx)(Qe,{gex:C.gex,spot:J.spot,india:n===`india`}),(0,X.jsx)($e,{smile:C.smile??null,atm:J.atm_strike})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Open interest by strike`,actions:n===`india`?(0,X.jsx)(b,{options:[{value:`oi`,label:`OI`},{value:`chg`,label:`Change in OI`}],value:re,onChange:e=>ie(e),size:`sm`}):void 0}),(0,X.jsx)(_,{children:(0,X.jsx)(`div`,{className:`h-56`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(te,{data:ue,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`strike`,tick:{fill:`var(--color-faint)`,fontSize:10},axisLine:!1,tickLine:!1,minTickGap:16}),(0,X.jsx)(B,{orientation:`right`,width:56,tickFormatter:e=>l(e),tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},formatter:(e,t)=>[l(Number(e)),t===`call`?`Calls`:`Puts`]}),(0,X.jsx)(z,{formatter:e=>e===`call`?`Calls`:`Puts`,wrapperStyle:{fontSize:12}}),J.atm_strike!=null&&(0,X.jsx)(L,{x:J.atm_strike,stroke:`var(--color-faint)`,strokeDasharray:`3 3`}),(0,X.jsx)(W,{dataKey:`call`,fill:`var(--color-down)`,fillOpacity:.75}),(0,X.jsx)(W,{dataKey:`put`,fill:`var(--color-up)`,fillOpacity:.75})]})})})})]}),(0,X.jsxs)(`div`,{className:`grid gap-6 2xl:grid-cols-[minmax(0,3fr)_minmax(0,2fr)]`,children:[(0,X.jsxs)(x,{className:`overflow-hidden`,children:[(0,X.jsx)(w,{title:`Option chain`,description:`Shaded = in the money. Click B / S to add a leg to the strategy.`,actions:(0,X.jsx)(`button`,{type:`button`,className:`text-xs text-muted hover:text-fg`,onClick:()=>N(e=>!e),children:M?`Near ATM only`:`All ${C.rows.length} strikes`})}),(0,X.jsx)(`div`,{className:`max-h-[32rem] overflow-auto`,children:(0,X.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,X.jsx)(`thead`,{className:`sticky top-0 z-10 border-y border-line bg-surface text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-end font-medium`,children:`OI`}),n===`india`&&(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-end font-medium`,children:`Chg OI`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-end font-medium`,children:`IV`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-end font-medium`,children:`Δ`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-end font-medium`,children:`Call LTP`}),(0,X.jsx)(`th`,{className:`bg-raised px-2 py-1.5 text-center font-semibold text-fg`,children:`Strike`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-start font-medium`,children:`Put LTP`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-start font-medium`,children:`Δ`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-start font-medium`,children:`IV`}),n===`india`&&(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-start font-medium`,children:`Chg OI`}),(0,X.jsx)(`th`,{className:`px-2 py-1.5 text-start font-medium`,children:`OI`})]})}),(0,X.jsx)(`tbody`,{className:`tabular divide-y divide-line`,children:oe.map(e=>{let t=e.strike<J.spot,r=e.strike===J.atm_strike;return(0,X.jsxs)(`tr`,{className:m(r&&`outline outline-1 -outline-offset-1 outline-accent`),children:[(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-end`,t&&`bg-down-soft/40`),children:l(e.call?.oi??null)}),n===`india`&&(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-end`,t&&`bg-down-soft/40`,(e.call?.chg_oi??0)>=0?`text-up`:`text-down`),children:l(e.call?.chg_oi??null)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-end`,t&&`bg-down-soft/40`),title:e.call?.iv_estimated?`Estimated from the price`:void 0,children:o(e.call?.iv,1)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-end text-muted`,t&&`bg-down-soft/40`),children:o(e.call?.delta,2)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-end`,t&&`bg-down-soft/40`),children:(0,X.jsx)(qe,{ltp:e.call?.ltp,onAdd:t=>ce(e,`call`,t),align:`right`})}),(0,X.jsx)(`td`,{className:`bg-raised px-2 py-1 text-center font-semibold`,children:o(e.strike,e.strike%1?1:0)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1`,!t&&`bg-up-soft/40`),children:(0,X.jsx)(qe,{ltp:e.put?.ltp,onAdd:t=>ce(e,`put`,t),align:`left`})}),(0,X.jsx)(`td`,{className:m(`px-2 py-1 text-muted`,!t&&`bg-up-soft/40`),children:o(e.put?.delta,2)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1`,!t&&`bg-up-soft/40`),title:e.put?.iv_estimated?`Estimated from the price`:void 0,children:o(e.put?.iv,1)}),n===`india`&&(0,X.jsx)(`td`,{className:m(`px-2 py-1`,!t&&`bg-up-soft/40`,(e.put?.chg_oi??0)>=0?`text-up`:`text-down`),children:l(e.put?.chg_oi??null)}),(0,X.jsx)(`td`,{className:m(`px-2 py-1`,!t&&`bg-up-soft/40`),children:l(e.put?.oi??null)})]},e.strike)})})]})})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Strategy builder`,description:`Payoff at expiry and today (Black-Scholes).`}),(0,X.jsxs)(_,{className:`space-y-4`,children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-[minmax(0,1fr)_120px] gap-2`,children:[(0,X.jsx)(v,{label:`Preset`,children:(0,X.jsx)(g,{options:[{value:``,label:`Choose a strategy…`},...Ge],value:``,onChange:e=>e.target.value&&le(e.target.value)})}),(0,X.jsx)(v,{label:n===`india`?`Lot size`:`Contract ×`,hint:n===`india`?`Verify with your broker`:void 0,children:(0,X.jsx)(y,{type:`number`,min:`1`,value:P,onChange:e=>ee(e.target.value)})})]}),G.length===0?(0,X.jsx)(D,{icon:`plus`,title:`No legs`,description:`Pick a preset or click B / S in the chain.`}):(0,X.jsx)(`ul`,{className:`divide-y divide-line rounded-lg border border-line text-sm`,children:G.map((e,t)=>(0,X.jsxs)(`li`,{className:`flex flex-wrap items-center gap-2 px-3 py-1.5`,children:[(0,X.jsx)(`button`,{type:`button`,onClick:()=>K(e=>e.map((e,n)=>n===t?{...e,side:e.side===`buy`?`sell`:`buy`}:e)),className:m(`w-10 rounded px-1 text-xs font-semibold uppercase`,e.side===`buy`?`bg-up-soft text-up`:`bg-down-soft text-down`),title:`Switch buy / sell`,children:e.side}),(0,X.jsx)(`span`,{className:`w-24 text-xs`,children:e.type===`stock`?`Underlying`:`${o(e.strike,e.strike%1?1:0)} ${e.type.toUpperCase()}`}),(0,X.jsx)(y,{type:`number`,step:`any`,value:e.premium,onChange:e=>K(n=>n.map((n,r)=>r===t?{...n,premium:parseFloat(e.target.value)||0}:n)),className:`w-24`,"aria-label":`Premium`}),(0,X.jsx)(`span`,{className:`text-xs text-muted`,children:`×`}),(0,X.jsx)(y,{type:`number`,min:`1`,value:e.quantity,onChange:e=>K(n=>n.map((n,r)=>r===t?{...n,quantity:parseFloat(e.target.value)||1}:n)),className:`w-20`,"aria-label":`Quantity`}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>K(e=>e.filter((e,n)=>n!==t)),className:`ms-auto rounded-md p-1 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Remove leg`,children:(0,X.jsx)(S,{name:`x`})})]},t))}),q&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-lg border border-line bg-line`,children:[(0,X.jsx)($,{label:q.net_premium>=0?`Net credit`:`Net debit`,value:r(Math.abs(q.net_premium),ae)}),(0,X.jsx)($,{label:`Breakeven`,value:q.breakevens.length?q.breakevens.map(e=>o(e)).join(` / `):`—`}),(0,X.jsx)($,{label:`Max profit`,value:q.max_profit==null?`Unlimited`:r(q.max_profit,ae),tone:`up`}),(0,X.jsx)($,{label:`Max loss`,value:q.max_loss==null?`Unlimited`:r(q.max_loss,ae),tone:`down`})]}),(0,X.jsx)(`div`,{className:`h-56`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(V,{data:q.points,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`price`,type:`number`,domain:[`dataMin`,`dataMax`],tickFormatter:e=>o(e,0),tick:{fill:`var(--color-faint)`,fontSize:10},axisLine:!1,tickLine:!1}),(0,X.jsx)(B,{orientation:`right`,width:60,tickFormatter:e=>l(e),tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},labelFormatter:e=>`At ${o(Number(e))}`,formatter:(e,t)=>[r(Number(e),ae),t===`expiry`?`At expiry`:`Today`]}),(0,X.jsx)(L,{y:0,stroke:`var(--color-line-strong)`}),(0,X.jsx)(L,{x:J.spot,stroke:`var(--color-accent)`,strokeDasharray:`3 3`,label:{value:`spot`,fill:`var(--color-faint)`,fontSize:10,position:`top`}}),(0,X.jsx)(I,{type:`linear`,dataKey:`expiry`,stroke:`var(--color-fg)`,dot:!1,strokeWidth:1.75}),(0,X.jsx)(I,{type:`monotone`,dataKey:`today`,stroke:`var(--color-accent)`,dot:!1,strokeWidth:1.25,strokeDasharray:`4 3`})]})})}),(0,X.jsx)(`div`,{className:`grid grid-cols-4 gap-2 text-center text-xs`,children:[`delta`,`gamma`,`theta`,`vega`].map(e=>(0,X.jsxs)(`div`,{className:`rounded-md border border-line px-2 py-1.5`,children:[(0,X.jsx)(`div`,{className:`text-muted capitalize`,children:e}),(0,X.jsx)(`div`,{className:`tabular font-medium`,children:o(q.greeks[e],e===`gamma`?4:2)})]},e))}),(0,X.jsx)(`p`,{className:`text-[12px] text-faint`,children:`Theta is per day and vega per 1 IV point, for the whole position. Taxes and brokerage aren't included.`})]})]})]})]})]})]})}function qe({ltp:e,onAdd:t,align:n}){return e==null?(0,X.jsx)(`span`,{className:`text-faint`,children:`—`}):(0,X.jsxs)(`span`,{className:m(`group inline-flex items-center gap-1`,n===`right`&&`flex-row-reverse`),children:[(0,X.jsx)(`span`,{className:`font-medium`,children:o(e)}),(0,X.jsxs)(`span`,{className:`flex gap-0.5 opacity-40 group-hover:opacity-100`,children:[(0,X.jsx)(`button`,{type:`button`,onClick:()=>t(`buy`),className:`rounded bg-up-soft px-1 text-[11px] font-bold text-up`,"aria-label":`Buy`,children:`B`}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>t(`sell`),className:`rounded bg-down-soft px-1 text-[11px] font-bold text-down`,"aria-label":`Sell`,children:`S`})]})]})}function $({label:e,value:t,sub:n,tone:r}){return(0,X.jsxs)(`div`,{className:`bg-surface px-3 py-2.5`,children:[(0,X.jsx)(`div`,{className:`text-[12px] text-muted`,children:e}),(0,X.jsx)(`div`,{className:m(`tabular text-sm font-semibold`,r===`up`&&`text-up`,r===`down`&&`text-down`),children:t}),n&&(0,X.jsx)(`div`,{className:`text-[12px] text-faint`,children:n})]})}var Je={expensive:{label:`Options look expensive`,tone:`text-down`,hint:`Implied volatility is well above what the stock has actually been doing. Premium sellers are paid more; option buyers need a bigger move to profit. Check for an event (results, budget) that could justify it.`},cheap:{label:`Options look cheap`,tone:`text-up`,hint:`Implied volatility is below recent realized volatility. Buying options costs less than the stock has been moving; selling premium pays little.`},fair:{label:`Options priced near recent movement`,tone:`text-fg`,hint:`Implied volatility is close to realized volatility - no clear edge for buyers or sellers from volatility alone.`}};function Ye({v:e}){let t=e.verdict?Je[e.verdict]:null,n=Math.max(e.rv_20_high,e.atm_iv??0,e.rv_20)*1.15,r=e=>`${e/n*100}%`;return(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Implied vs realized volatility`,description:`What options are pricing in, against how much the underlying has really been moving`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-baseline justify-between gap-2`,children:[(0,X.jsx)(`div`,{className:m(`text-sm font-semibold`,t?.tone),children:t?t.label:`No ATM implied volatility for this expiry`}),e.ratio!=null&&(0,X.jsxs)(`div`,{className:`tabular text-sm text-muted`,children:[`IV / RV = `,o(e.ratio),`×`]})]}),(0,X.jsxs)(`div`,{className:`relative h-8`,children:[(0,X.jsx)(`div`,{className:`absolute top-3 h-2 w-full rounded-full bg-raised`}),(0,X.jsx)(`div`,{className:`absolute top-3 h-2 rounded-full bg-accent/30`,style:{left:r(e.rv_20_low),width:`calc(${r(e.rv_20_high)} - ${r(e.rv_20_low)})`},title:`Usual range of 20-day realized volatility over the past year (10th-90th percentile)`}),(0,X.jsx)(`div`,{className:`absolute top-1.5 h-5 w-1 rounded-full bg-fg`,style:{left:`calc(${r(e.rv_20)} - 2px)`},title:`Realized (20d) ${e.rv_20}%`}),e.atm_iv!=null&&(0,X.jsx)(`div`,{className:`absolute top-1 h-6 w-1.5 rounded-full bg-warn`,style:{left:`calc(${r(e.atm_iv)} - 3px)`},title:`ATM implied ${e.atm_iv}%`})]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-x-5 gap-y-1 text-xs text-muted`,children:[(0,X.jsxs)(`span`,{children:[(0,X.jsx)(`span`,{className:`me-1 inline-block h-2 w-2 rounded-full bg-warn`}),`ATM IV `,e.atm_iv==null?`—`:`${e.atm_iv}%`]}),(0,X.jsxs)(`span`,{children:[(0,X.jsx)(`span`,{className:`me-1 inline-block h-2 w-2 rounded-full bg-fg`}),`Realized 20d `,e.rv_20,`%`]}),(0,X.jsxs)(`span`,{children:[`Realized 60d `,e.rv_60==null?`—`:`${e.rv_60}%`]}),(0,X.jsxs)(`span`,{children:[(0,X.jsx)(`span`,{className:`me-1 inline-block h-2 w-2 rounded-full bg-accent/40`}),`Usual 20d range `,e.rv_20_low,`-`,e.rv_20_high,`%`]})]}),t&&(0,X.jsx)(`p`,{className:`text-xs text-faint`,children:t.hint})]})]})}var Xe={background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},Ze=(e,t)=>Math.abs(e/t-1)<=.1;function Qe({gex:e,spot:t,india:n}){let r=e.by_strike.filter(e=>Ze(e.strike,t)),i=e.total>=0,a=e=>n?`₹${(e/1e7).toLocaleString(`en-IN`,{maximumFractionDigits:Math.abs(e)>=1e9?0:1})} cr`:`$${l(e)}`;return(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Gamma exposure by strike`,description:`Estimated dealer gamma, per 1% move of the underlying`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-3 gap-3 text-sm`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:`Net gamma`}),(0,X.jsx)(`div`,{className:m(`tabular font-semibold`,i?`text-up`:`text-down`),children:a(e.total)})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:`Zero-gamma level`}),(0,X.jsx)(`div`,{className:`tabular font-semibold`,children:e.zero_gamma==null?`—`:o(e.zero_gamma,0)})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:`Largest at strike`}),(0,X.jsx)(`div`,{className:`tabular font-semibold`,children:e.peak_strike==null?`—`:o(e.peak_strike,0)})]})]}),(0,X.jsx)(`div`,{className:`h-52`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(te,{data:r,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`strike`,tick:{fill:`var(--color-faint)`,fontSize:10},axisLine:!1,tickLine:!1,minTickGap:16}),(0,X.jsx)(B,{orientation:`right`,width:n?72:56,tickFormatter:e=>a(e),tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1}),(0,X.jsx)(F,{contentStyle:Xe,formatter:e=>[a(Number(e)),`Net gamma per 1%`]}),(0,X.jsx)(L,{y:0,stroke:`var(--color-line-strong)`}),(0,X.jsx)(L,{x:r.reduce((e,n)=>Math.abs(n.strike-t)<Math.abs(e-t)?n.strike:e,r[0]?.strike??t),stroke:`var(--color-faint)`,strokeDasharray:`3 3`}),(0,X.jsx)(W,{dataKey:`net`,fill:`var(--color-accent)`,fillOpacity:.8})]})})}),(0,X.jsxs)(`p`,{className:`text-[12px] text-faint`,children:[i?`Net positive: under this convention dealers hedge against moves (sell rallies, buy dips), which tends to damp swings.`:`Net negative: under this convention dealers hedge with moves (sell into falls, buy into rallies), which can widen swings.`,` `,`Gamma x open interest x contract size (`,o(e.multiplier,0),`) x spot² x 1%; calls counted positive, puts negative, as public gamma estimates assume. Real dealer positions are not published, so this is an estimate.`,e.interpolated_iv&&` Strikes with no solvable IV use their neighbours' IV.`,` Dashed line: spot.`]})]})]})}function $e({smile:e,atm:t}){let n=e?.points??[];return(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Volatility smile`,description:`Implied volatility by strike for this expiry`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[e?.same_day&&(0,X.jsx)(`p`,{className:`text-xs text-warn`,children:`Expires today: with only hours left, implied volatilities jump around. A later expiry gives a steadier picture.`}),n.length<3?(0,X.jsx)(`p`,{className:`text-sm text-muted`,children:`Too few strikes with an implied volatility for this expiry.`}):(0,X.jsx)(`div`,{className:`h-60`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(V,{data:n,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`strike`,tick:{fill:`var(--color-faint)`,fontSize:10},axisLine:!1,tickLine:!1,minTickGap:16}),(0,X.jsx)(B,{orientation:`right`,width:44,domain:[`auto`,`auto`],tickFormatter:e=>`${e}%`,tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1}),(0,X.jsx)(F,{contentStyle:Xe,formatter:e=>[`${o(Number(e))}%`,`Implied volatility`]}),t!=null&&(0,X.jsx)(L,{x:t,stroke:`var(--color-faint)`,strokeDasharray:`3 3`}),(0,X.jsx)(I,{type:`monotone`,dataKey:`iv`,stroke:`var(--color-accent)`,dot:{r:1.5},strokeWidth:1.8,connectNulls:!0})]})})}),(0,X.jsxs)(`p`,{className:`text-[12px] text-faint`,children:[`Out-of-the-money options (puts below the forward, calls above), each IV solved against the forward level implied by put-call parity`,e?.forward!=null&&` (${o(e.forward)})`,`, so calls and puts agree. Higher IV on low strikes than on high ones (a skew) means protection against falls costs more than bets on rises. Dashed line: the at-the-money strike. Strikes within 10%.`]})]})]})}var et=[{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`},{value:`5y`,label:`5Y`}],tt={cointegrated:{title:`Cointegrated`,className:`bg-up-soft text-up`},stretched:{title:`Cointegrated, spread stretched`,className:`bg-warn-soft text-warn`},not_cointegrated:{title:`Not cointegrated`,className:`bg-raised text-muted`}};function nt({symbol:e,market:t}){let[n,r]=(0,Y.useState)(e),[i,s]=(0,Y.useState)(t),[c,l]=(0,Y.useState)(``),[u,d]=(0,Y.useState)(t),[f,p]=(0,Y.useState)(`2y`),[h,g]=(0,Y.useState)(null),[y,S]=(0,Y.useState)(null),[C,T]=(0,Y.useState)(!1);async function O(){if(n.trim()&&c.trim()){T(!0),S(null);try{g(await pe({a:n,b:c,market:i,market_b:u,period:f}))}catch(e){g(null),S(a(e))}finally{T(!1)}}}let k=h?tt[h.verdict]:null,A=h&&Math.abs(h.z_now)>=2?h.z_now>0?`${h.a} is rich vs ${h.b}`:`${h.a} is cheap vs ${h.b}`:null;return(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Pairs test`,description:`Do two prices move apart and come back? (Engle-Granger cointegration)`,icon:`analyze`}),(0,X.jsxs)(_,{children:[(0,X.jsxs)(`form`,{className:`grid gap-3 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto_auto] md:items-end`,onSubmit:e=>{e.preventDefault(),O()},children:[(0,X.jsx)(v,{label:`Symbol A`,children:(0,X.jsx)(Me,{value:n,onChange:r,onSelect:e=>(r(e.symbol),s(e.market)),placeholder:`e.g. KO`})}),(0,X.jsx)(v,{label:`Symbol B`,children:(0,X.jsx)(Me,{value:c,onChange:l,onSelect:e=>(l(e.symbol),d(e.market)),placeholder:`e.g. PEP`})}),(0,X.jsx)(v,{label:`History`,children:(0,X.jsx)(b,{options:et,value:f,onChange:p,size:`sm`})}),(0,X.jsx)(E,{type:`submit`,icon:`analyze`,loading:C,disabled:!n.trim()||!c.trim(),children:`Test pair`})]}),y&&(0,X.jsx)(`p`,{className:`mt-3 text-sm text-down`,children:y})]})]}),h?(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`${h.a} vs ${h.b}`,description:`${h.days} shared trading days, ${h.start} to ${h.end}`,actions:k&&(0,X.jsx)(`span`,{className:m(`rounded-md px-2 py-1 text-xs font-medium`,k.className),children:k.title})}),(0,X.jsxs)(_,{className:`space-y-5`,children:[(0,X.jsx)(`div`,{className:`grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6`,children:[[`ADF statistic`,o(h.adf_stat),h.significance?`significant at ${h.significance}`:`needs < ${o(h.critical[`10%`])}`],[`Spread now`,`${h.z_now>0?`+`:``}${o(h.z_now)} σ`,A??`within normal range`],[`Half-life`,h.half_life_days==null?`—`:`${o(h.half_life_days,1)} days`,`time to close half the gap`],[`Hedge ratio`,o(h.hedge_ratio,3),`1% in ${h.b} ≈ ${o(h.hedge_ratio,2)}% in ${h.a}`],[`Return correlation`,o(h.correlation),`daily moves`],[`ADF lags`,String(h.adf_lag),`chosen by BIC`]].map(([e,t,n])=>(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`text-xs text-faint`,children:e}),(0,X.jsx)(`div`,{className:`tabular text-base font-semibold`,children:t}),(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:n})]},e))}),(0,X.jsx)(`div`,{className:`h-64`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(V,{data:h.spread,margin:{top:4,right:8,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`time`,tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,minTickGap:50,tickFormatter:e=>new Date(e).toLocaleDateString(void 0,{month:`short`,year:`2-digit`})}),(0,X.jsx)(B,{width:36,domain:[`auto`,`auto`],tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,tickFormatter:e=>`${o(e,0)}σ`}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},formatter:e=>[`${o(Number(e))} σ`,`Spread`]}),(0,X.jsx)(L,{y:0,stroke:`var(--color-line-strong)`}),(0,X.jsx)(L,{y:2,stroke:`var(--color-warn)`,strokeDasharray:`4 3`}),(0,X.jsx)(L,{y:-2,stroke:`var(--color-warn)`,strokeDasharray:`4 3`}),(0,X.jsx)(I,{dataKey:`z`,stroke:`var(--color-accent)`,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]})})}),(0,X.jsxs)(`p`,{className:`text-xs text-faint`,children:[`Spread = log(`,h.a,`) − `,o(h.hedge_ratio,3),` × log(`,h.b,`), in standard deviations from its mean. Dashed lines at ±2σ.`,h.verdict===`not_cointegrated`?` The spread has not reliably returned to its mean over this window, so a stretched spread is not a signal here.`:` Past behaviour only; relationships break (mergers, regulation, one company stumbling). Not investment advice.`]})]})]}):!y&&(0,X.jsx)(x,{children:(0,X.jsx)(D,{icon:`analyze`,title:`Pick two related instruments`,description:`Same-sector stocks (two banks, two oil majors) or two funds on the same index. Cointegrated pairs tend to snap back when their spread stretches.`})})]})}function rt({onStatus:e}){let[t,n]=(0,Y.useState)(null),[i,s]=(0,Y.useState)(null),[c,l]=(0,Y.useState)(null),[u,d]=(0,Y.useState)(!1),h=(0,Y.useCallback)(()=>{oe().then(t=>{n(t),s(e=>e??t.settings),l(null),e?.(t)}).catch(e=>l(a(e)))},[e]);(0,Y.useEffect)(()=>{h();let e=window.setInterval(h,3e4);return()=>window.clearInterval(e)},[h]);async function b(){if(i){d(!0);try{let e=await re(i);s(e),f.success(`Risk rules saved`),h()}catch(e){f.error(a(e))}finally{d(!1)}}}if(c)return(0,X.jsx)(O,{title:`Risk status unavailable`,children:c});if(!t||!i)return(0,X.jsx)(A,{className:`h-80 w-full`});let S=Z[t.settings.market],T=e=>s(t=>t&&{...t,...e}),k=Math.min(100,t.limit_used_pct??0);return(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[340px_minmax(0,1fr)]`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Daily rules`,description:`Guard rails for your journal's trades. Nothing is blocked; you get a warning and one alert.`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsx)(v,{label:`Market (currency) the rules cover`,children:(0,X.jsx)(g,{options:Ae,value:i.market,onChange:e=>T({market:e.target.value})})}),(0,X.jsx)(v,{label:`Trading capital (${Z[i.market]??``})`,children:(0,X.jsx)(y,{type:`number`,value:i.capital,onChange:e=>T({capital:parseFloat(e.target.value)||0})})}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,X.jsx)(v,{label:`Daily loss limit %`,children:(0,X.jsx)(y,{type:`number`,step:`0.1`,value:i.daily_loss_limit_pct,onChange:e=>T({daily_loss_limit_pct:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Max open risk %`,children:(0,X.jsx)(y,{type:`number`,step:`0.5`,value:i.max_open_risk_pct,onChange:e=>T({max_open_risk_pct:parseFloat(e.target.value)||0})})}),(0,X.jsx)(v,{label:`Max trades a day`,children:(0,X.jsx)(y,{type:`number`,min:`0`,value:i.max_trades_per_day,onChange:e=>T({max_trades_per_day:parseInt(e.target.value,10)||0})})})]}),(0,X.jsx)(p,{checked:i.notify,onChange:e=>T({notify:e}),label:`Alert me when the limit is hit`,description:`Once a day, through your alert channels.`}),(0,X.jsx)(E,{onClick:b,loading:u,children:`Save rules`})]})]}),(0,X.jsxs)(`div`,{className:`space-y-6`,children:[t.status===`stop`?(0,X.jsx)(O,{tone:`warn`,title:`Stop trading for today`,children:t.reasons[0]}):t.reasons.length?(0,X.jsx)(O,{tone:`accent`,title:`Heads up`,children:(0,X.jsx)(`ul`,{className:`list-disc ps-4`,children:t.reasons.map(e=>(0,X.jsx)(`li`,{children:e},e))})}):null,(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Today`,description:`${Ae.find(e=>e.value===t.settings.market)?.label??t.settings.market} trades · refreshes every 30s`,actions:(0,X.jsx)(C,{tone:t.status===`ok`?`up`:t.status===`warn`?`warn`:`down`,children:t.status===`ok`?`Within limits`:t.status===`warn`?`Warning`:`Limit hit`})}),(0,X.jsxs)(_,{className:`space-y-4`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsxs)(`div`,{className:`mb-1 flex justify-between text-xs text-muted`,children:[(0,X.jsx)(`span`,{children:`Loss limit used`}),(0,X.jsxs)(`span`,{className:`tabular`,children:[r(Math.max(0,-t.day_pnl),S),` of `,r(t.loss_limit,S)]})]}),(0,X.jsx)(`div`,{className:`h-2 overflow-hidden rounded-full bg-line`,children:(0,X.jsx)(`div`,{className:m(`h-full rounded-full`,k>=100?`bg-down`:k>=75?`bg-warn`:`bg-up`),style:{width:`${k}%`}})})]}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-lg border border-line bg-line sm:grid-cols-4`,children:[(0,X.jsx)(it,{label:`Net P&L today`,value:r(t.day_pnl,S),tone:t.day_pnl>=0?`up`:`down`}),(0,X.jsx)(it,{label:`Realised`,value:r(t.realized,S),sub:`${t.closed_today} closed`}),(0,X.jsx)(it,{label:`Open P&L`,value:r(t.unrealized,S)}),(0,X.jsx)(it,{label:`Open risk to stops`,value:r(t.open_risk,S),sub:`${o(t.open_risk_pct)}% of capital (cap ${t.settings.max_open_risk_pct}%)`}),(0,X.jsx)(it,{label:`Trades today`,value:`${t.trades_today} / ${t.settings.max_trades_per_day||`∞`}`})]})]})]}),(0,X.jsxs)(x,{className:`overflow-hidden`,children:[(0,X.jsx)(w,{title:`Open positions`}),t.positions.length===0?(0,X.jsx)(D,{icon:`portfolio`,title:`No open trades`,description:`Open trades from the Journal show here with live P&L.`}):(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`border-y border-line text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Stock`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Qty`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Entry`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Now`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Stop`}),(0,X.jsx)(`th`,{className:`px-4 py-2 text-end font-medium`,children:`P&L`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:t.positions.map(e=>(0,X.jsxs)(`tr`,{children:[(0,X.jsxs)(`td`,{className:`px-4 py-2`,children:[(0,X.jsx)(`span`,{className:`font-mono font-medium`,children:e.symbol}),(0,X.jsx)(`span`,{className:m(`ms-1.5 text-[12px] uppercase`,e.side===`short`?`text-down`:`text-up`),children:e.side})]}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:o(e.quantity,e.quantity%1?4:0)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:r(e.entry_price,S)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:r(e.price,S)}),(0,X.jsx)(`td`,{className:m(`tabular px-3 py-2 text-end`,e.stop==null&&`text-warn`),children:e.stop==null?`none`:r(e.stop,S)}),(0,X.jsx)(`td`,{className:m(`tabular px-4 py-2 text-end`,(e.pnl??0)>=0?`text-up`:`text-down`),children:r(e.pnl,S)})]},e.id))})]})]})]})]})}function it({label:e,value:t,sub:n,tone:r}){return(0,X.jsxs)(`div`,{className:`bg-surface px-3 py-2.5`,children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:e}),(0,X.jsx)(`div`,{className:m(`tabular text-sm font-semibold`,r===`up`&&`text-up`,r===`down`&&`text-down`),children:t}),n&&(0,X.jsx)(`div`,{className:`text-[12px] text-faint`,children:n})]})}var at=[{name:`Breakouts`,scans:[`high_52w`,`breakout_20d`,`volume_surge`],match:`any`},{name:`Momentum`,scans:[`ema_cross_up`,`supertrend_buy`,`uptrend`],match:`any`},{name:`Oversold bounce`,scans:[`rsi_oversold`,`near_support`,`open_low`],match:`any`},{name:`Gappers`,scans:[`gap_up`,`gap_down`,`big_mover`],match:`any`},{name:`Intraday ORB`,scans:[`orb_up`,`orb_down`,`vwap_cross_up`,`vwap_cross_down`],match:`any`},{name:`Coiled (NR7 inside day)`,scans:[`nr7`,`inside_day`],match:`all`}],ot=new Set([`gap_down`,`low_52w`,`breakdown_20d`,`rsi_overbought`,`ema_cross_down`,`supertrend_sell`,`open_high`,`orb_down`,`vwap_cross_down`]),st=new Set([`big_mover`,`volume_surge`,`inside_day`,`nr7`]),ct=[50,100,200,500].map(e=>({value:String(e),label:`Top ${e}`}));function lt({market:e,onOpen:t}){let[n,s]=(0,Y.useState)([]),[l,u]=(0,Y.useState)(null),[d,h]=(0,Y.useState)([]),[T,O]=(0,Y.useState)({universe:{sources:[`top`],market:e===`global`?`us`:e,top_n:100,watchlist_ids:[],portfolio_names:[],symbols:[]},scans:at[0].scans,params:{},match:`any`}),[A,j]=(0,Y.useState)(null),[N,P]=(0,Y.useState)(!1),[F,I]=(0,Y.useState)(``),[L,R]=(0,Y.useState)(!0),[z,B]=(0,Y.useState)(`15`),[V,H]=(0,Y.useState)(``);(0,Y.useEffect)(()=>{Te().then(s).catch(()=>s([])),M().then(u).catch(()=>u({watchlists:[],portfolios:[]})),U()},[]);function U(){q().then(h).catch(()=>h([]))}let W=(0,Y.useMemo)(()=>Object.fromEntries(n.map(e=>[e.id,e])),[n]),ee=(0,Y.useMemo)(()=>{let e={};return n.forEach(t=>(e[t.group]??=[]).push(t)),Object.entries(e)},[n]),te=e=>O(t=>({...t,universe:{...t.universe,...e}})),G=e=>te({sources:T.universe.sources.includes(e)?T.universe.sources.filter(t=>t!==e):[...T.universe.sources,e]}),K=e=>O(t=>({...t,scans:t.scans.includes(e)?t.scans.filter(t=>t!==e):[...t.scans,e]}));async function re(){P(!0),j(null);try{let e=await ae(T);j(e),e.failed.length&&f.info(`${e.failed.length} symbol(s) had no data`)}catch(e){f.error(a(e))}finally{P(!1)}}async function ie(){if(F.trim())try{await ne({...T,name:F.trim(),notify:L,interval_minutes:Math.max(5,parseInt(z,10)||15)}),f.success(`Scan saved`),I(``),U()}catch(e){f.error(a(e))}}let J=(A?.rows??[]).filter(e=>!V||e.symbol.toLowerCase().includes(V.toLowerCase())||(e.name??``).toLowerCase().includes(V.toLowerCase())),oe=T.universe.sources.length===0||T.universe.sources.length===1&&T.universe.sources[0]===`custom`&&!T.universe.symbols.length;return(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[380px_minmax(0,1fr)]`,children:[(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Scan`,icon:`search`}),(0,X.jsxs)(_,{className:`space-y-5`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:`Presets`}),(0,X.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:at.map(e=>(0,X.jsx)(`button`,{type:`button`,onClick:()=>O(t=>({...t,scans:e.scans,match:e.match})),className:`rounded-full border border-line px-2.5 py-0.5 text-xs text-muted hover:border-line-strong hover:text-fg`,children:e.name},e.name))})]}),(0,X.jsxs)(`div`,{className:`space-y-2`,children:[(0,X.jsx)(`span`,{className:`block text-xs font-medium text-muted`,children:`Universe`}),(0,X.jsx)(ut,{on:T.universe.sources.includes(`top`),onToggle:()=>G(`top`),title:`Largest stocks`,children:(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,X.jsx)(g,{options:Ae.filter(e=>e.value!==`global`),value:T.universe.market,onChange:e=>te({market:e.target.value})}),(0,X.jsx)(g,{options:ct,value:String(T.universe.top_n),onChange:e=>te({top_n:Number(e.target.value)})})]})}),(0,X.jsx)(ut,{on:T.universe.sources.includes(`watchlist`),onToggle:()=>G(`watchlist`),title:`Watchlists${l?` · ${l.watchlists.reduce((e,t)=>e+t.symbols.length,0)}`:``}`}),(0,X.jsx)(ut,{on:T.universe.sources.includes(`portfolio`),onToggle:()=>G(`portfolio`),title:`Portfolio holdings${l?` · ${l.portfolios.reduce((e,t)=>e+t.symbols.length,0)}`:``}`}),(0,X.jsx)(ut,{on:T.universe.sources.includes(`custom`),onToggle:()=>G(`custom`),title:`Custom list`,children:(0,X.jsx)(k,{values:T.universe.symbols,onChange:e=>te({symbols:e}),placeholder:`Symbols in the market above`})})]}),(0,X.jsxs)(`div`,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,X.jsxs)(`span`,{className:`text-xs font-medium text-muted`,children:[`Scans (`,T.scans.length,`)`]}),(0,X.jsx)(b,{options:[{value:`any`,label:`Match any`},{value:`all`,label:`Match all`}],value:T.match,onChange:e=>O(t=>({...t,match:e})),size:`sm`})]}),ee.map(([e,t])=>(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`div`,{className:`mb-1 text-[12px] font-medium tracking-wide text-faint uppercase`,children:e}),(0,X.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:t.map(e=>{let t=T.scans.includes(e.id);return(0,X.jsx)(`button`,{type:`button`,"aria-pressed":t,onClick:()=>K(e.id),className:m(`rounded-full border px-2.5 py-0.5 text-xs font-medium`,t?`border-accent bg-accent-soft text-fg`:`border-line text-muted hover:text-fg`),children:e.label},e.id)})})]},e)),T.scans.some(e=>W[e]?.param)&&(0,X.jsx)(`div`,{className:`grid grid-cols-2 gap-2 rounded-lg border border-line p-2.5`,children:T.scans.filter(e=>W[e]?.param).map(e=>(0,X.jsxs)(`label`,{className:`text-[12px] text-muted`,children:[W[e].label,` · `,W[e].param,(0,X.jsx)(y,{type:`number`,step:`any`,value:T.params[e]??W[e].default??``,onChange:t=>O(n=>({...n,params:{...n.params,[e]:parseFloat(t.target.value)}})),className:`mt-0.5`})]},e))})]}),(0,X.jsx)(E,{onClick:re,loading:N,disabled:!T.scans.length||oe,icon:`search`,className:`w-full`,children:N?`Scanning…`:`Run scan`})]})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Save & get alerts`,description:`Runs every N minutes while the market is open and sends only new matches.`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsx)(y,{value:F,onChange:e=>I(e.target.value),placeholder:`Name, e.g. Nifty 100 breakouts`}),(0,X.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,X.jsx)(p,{checked:L,onChange:R,label:(0,X.jsx)(`span`,{className:`text-sm`,children:`Notify me`})}),(0,X.jsx)(v,{label:`Every (min)`,className:`w-28`,children:(0,X.jsx)(y,{type:`number`,min:`5`,value:z,onChange:e=>B(e.target.value)})})]}),(0,X.jsx)(E,{size:`sm`,variant:`secondary`,onClick:ie,disabled:!F.trim()||!T.scans.length,children:`Save scan`}),d.length>0&&(0,X.jsx)(`ul`,{className:`divide-y divide-line rounded-lg border border-line`,children:d.map(e=>(0,X.jsxs)(`li`,{className:`flex flex-wrap items-center gap-2 px-3 py-2 text-sm`,children:[(0,X.jsxs)(`button`,{type:`button`,className:`min-w-0 flex-1 truncate text-start hover:underline`,onClick:()=>O({universe:e.universe,scans:e.scans,params:e.params??{},match:e.match}),title:`Load into the form`,children:[e.name,(0,X.jsxs)(`span`,{className:`block text-[12px] text-muted`,children:[e.last_run_at?`${e.last_count??0} matches · ${i(e.last_run_at)}`:`not run yet`,e.notify&&` · every ${e.interval_minutes}m`]})]}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>he(e.id,{notify:!e.notify}).then(U,e=>f.error(a(e))),className:m(`rounded-md p-1.5`,e.notify?`text-accent-fg`:`text-faint hover:text-fg`),"aria-label":e.notify?`Turn notifications off`:`Turn notifications on`,title:e.notify?`Notifications on`:`Notifications off`,children:(0,X.jsx)(S,{name:`bell`})}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>se(e.id).then(U),className:`rounded-md p-1.5 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Delete ${e.name}`,children:(0,X.jsx)(S,{name:`trash`})})]},e.id))})]})]})]}),(0,X.jsxs)(x,{className:`overflow-hidden`,children:[(0,X.jsx)(w,{title:`Results`,description:A?`${A.rows.length} match${A.rows.length===1?``:`es`} out of ${A.scanned} stocks · ${A.seconds}s`:`Pick a universe and scans, then run.`,actions:A&&A.rows.length>0?(0,X.jsxs)(`div`,{className:`flex items-center gap-2`,children:[A.rows.length>5&&(0,X.jsx)(y,{value:V,onChange:e=>H(e.target.value),placeholder:`Filter`,className:`w-36`}),(0,X.jsx)(Ne,{title:`Scan results`,subtitle:`${A.rows.length} matches of ${A.scanned}`,tables:()=>[{title:`Scan results`,columns:[{key:`symbol`,label:`Symbol`},{key:`name`,label:`Name`},{key:`market`,label:`Market`},{key:`price`,label:`Price`,kind:`number`},{key:`change_percent`,label:`Change %`,kind:`pct`},{key:`gap_percent`,label:`Gap %`,kind:`pct`},{key:`volume_ratio`,label:`Volume x avg`,kind:`number`},{key:`rsi`,label:`RSI`,kind:`number`,digits:1},{key:`matched`,label:`Matched scans`},{key:`reasons`,label:`Why`}],rows:J}]})]}):void 0}),N?(0,X.jsx)(_,{children:(0,X.jsx)(`p`,{className:`text-sm text-muted`,children:`Downloading bars and scanning… large universes take 10–30 seconds.`})}):A?J.length===0?(0,X.jsx)(D,{icon:`search`,title:`No matches`,description:`Try Match any, fewer scans or a bigger universe.`}):(0,X.jsx)(`div`,{className:`overflow-x-auto`,children:(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`border-y border-line text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Stock`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Price`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Change`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Gap`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Vol ×`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`RSI`}),(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Signals`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:J.map(e=>(0,X.jsxs)(`tr`,{className:`align-top hover:bg-raised/50`,children:[(0,X.jsxs)(`td`,{className:`px-4 py-2`,children:[(0,X.jsx)(`button`,{type:`button`,onClick:()=>t(e.symbol,e.market),className:`font-mono font-medium hover:underline`,children:e.symbol}),e.name&&(0,X.jsx)(`div`,{className:`max-w-44 truncate text-xs text-muted`,children:e.name})]}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:r(e.price,Z[e.market])}),(0,X.jsx)(`td`,{className:m(`tabular px-3 py-2 text-end`,e.change_percent>=0?`text-up`:`text-down`),children:c(e.change_percent)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end text-xs`,children:c(e.gap_percent,1)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:e.volume_ratio==null?`—`:o(e.volume_ratio,1)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:o(e.rsi,0)}),(0,X.jsxs)(`td`,{className:`px-4 py-2`,children:[(0,X.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.matched.map((t,n)=>(0,X.jsx)(`span`,{title:e.reasons[n],children:(0,X.jsx)(C,{tone:ot.has(t)?`down`:st.has(t)?`neutral`:`up`,children:W[t]?.label??t})},t))}),(0,X.jsx)(`div`,{className:`mt-0.5 text-[12px] text-muted`,children:e.reasons.slice(0,2).join(` · `)})]})]},`${e.market}:${e.symbol}`))})]})}):(0,X.jsx)(D,{icon:`search`,title:`No scan run yet`,description:`Daily bars include today's live bar; intraday scans use 5-minute bars.`})]})]})}function ut({on:e,onToggle:t,title:n,children:r}){return(0,X.jsxs)(`div`,{className:m(`rounded-lg border px-3 py-2`,e?`border-accent/60 bg-accent-soft/40`:`border-line`),children:[(0,X.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2.5 text-sm`,children:[(0,X.jsx)(`input`,{type:`checkbox`,checked:e,onChange:t,className:`h-4 w-4 accent-[var(--color-accent)]`}),n]}),e&&r&&(0,X.jsx)(`div`,{className:`mt-2`,children:r})]})}var dt={"1m":`1m`,"5m":`5m`,"15m":`15m`,"30m":`30m`,"1h":`1h`,"1d":`1d`,"1wk":`1w`};function ft(e){let t=e.toUpperCase().split(`-`)[0];return(t.endsWith(`USDT`)?t:`${t}USDT`).toLowerCase()}function pt(e,t,n,r){let[i,a]=(0,Y.useState)(null),o=e=>a(t=>({...e,count:(t?.count??0)+1,direction:!t||e.price===t.price?`flat`:e.price>t.price?`up`:`down`}));return(0,Y.useEffect)(()=>{if(a(null),!r||!e)return;if(t===`crypto`){let t=`wss://stream.binance.com:9443/ws/${ft(e)}@kline_${dt[n]??`1m`}`,r=null,i,a=!1,s=()=>{r=new WebSocket(t),r.onmessage=e=>{let t=JSON.parse(e.data)?.k;if(!t)return;let n={time:Math.floor(t.t/1e3),open:+t.o,high:+t.h,low:+t.l,close:+t.c,volume:+t.v};o({price:n.close,changePercent:null,bar:n,source:`binance`,at:Date.now()})},r.onclose=()=>{a||(i=window.setTimeout(s,3e3))}};return s(),()=>{a=!0,window.clearTimeout(i),r?.close()}}let i=new EventSource(`/api/v1/trade/stream?symbols=${encodeURIComponent(`${t}:${e}`)}&every=5`);return i.onmessage=e=>{let t=JSON.parse(e.data);typeof t.price==`number`&&o({price:t.price,changePercent:t.change_percent??null,bar:null,source:`server`,at:Date.now()})},()=>i.close()},[e,t,n,r]),i}var mt=(0,Y.lazy)(()=>d(()=>import(`./TradeChart-ZjsycacC.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))),ht=[{value:`1m`,label:`1m`},{value:`5m`,label:`5m`},{value:`15m`,label:`15m`},{value:`30m`,label:`30m`},{value:`1h`,label:`1h`},{value:`1d`,label:`1D`},{value:`1wk`,label:`1W`}],gt=[{id:`vwap`,label:`VWAP`},{id:`ema9`,label:`EMA 9`},{id:`ema21`,label:`EMA 21`},{id:`ema50`,label:`EMA 50`},{id:`ema200`,label:`EMA 200`},{id:`supertrend`,label:`Supertrend`},{id:`vwma`,label:`VWMA 13/19 + kNN (exp.)`},{id:`knn_st`,label:`kNN Supertrend (exp.)`}],_t=[{id:`pivots`,label:`Pivots`},{id:`or`,label:`Opening range`},{id:`alerts`,label:`My alerts`}],vt=`marketmyna.tradeChart`;function yt(){let e={interval:`5m`,indicators:[`vwap`,`ema9`,`ema21`],overlays:[`pivots`,`alerts`],live:!0};try{return{...e,...JSON.parse(localStorage.getItem(vt)??`{}`)}}catch{return e}}function bt(e){try{localStorage.setItem(vt,JSON.stringify(e))}catch{}}function xt({symbol:e,market:t,alerts:n,onAlertsChanged:i,onSize:s}){let[c,l]=(0,Y.useState)(yt),[u,d]=(0,Y.useState)(null),[h,g]=(0,Y.useState)(null),[v,S]=(0,Y.useState)(null),[C,T]=(0,Y.useState)(null),[D,O]=(0,Y.useState)(``),[k,j]=(0,Y.useState)(!1),M=![`1d`,`1wk`].includes(c.interval),N=Z[t];function P(e){l(t=>{let n={...t,...e};return bt(n),n})}let F=(0,Y.useCallback)((n=!1)=>(n||(d(null),g(null)),ce(e,t,c.interval,void 0,c.indicators).then(e=>{d(e),g(null)}).catch(e=>!n&&g(a(e)))),[e,t,c.interval,c.indicators]);(0,Y.useEffect)(()=>{F()},[F]),(0,Y.useEffect)(()=>{if(!c.live||!M)return;let e=window.setInterval(()=>F(!0),6e4);return()=>window.clearInterval(e)},[c.live,M,F]),(0,Y.useEffect)(()=>{S(null),T(null),ue(e,t).then(S).catch(()=>S(null))},[e,t]);let I=(0,Y.useMemo)(()=>{let e=[],t=e=>c.overlays.includes(e);if(t(`pivots`)&&u?.pivots)for(let[t,n]of Object.entries(u.pivots))e.push({price:n,label:t,color:t===`P`?`#9aa3b5`:t.startsWith(`R`)?`#fb8a8a99`:`#34d39999`,dashed:!0});if(t(`or`)&&u?.opening_range&&(e.push({price:u.opening_range.high,label:`OR high`,color:`#f5b942`,dashed:!0}),e.push({price:u.opening_range.low,label:`OR low`,color:`#f5b942`,dashed:!0})),t(`alerts`))for(let t of n)(t.kind===`price_above`||t.kind===`price_below`)&&t.status===`active`&&e.push({price:t.value,label:`🔔 ${t.kind===`price_above`?`≥`:`≤`}`,color:`#6d8cff`});return C!=null&&e.push({price:C,label:`Picked`,color:`#9aa3b5`,dashed:!0}),e},[u,n,c.overlays,C]),L=pt(e,t,c.interval,c.live),[R,z]=(0,Y.useState)(null),[,B]=(0,Y.useState)(0);(0,Y.useEffect)(()=>{let e=()=>be(t).then(z,()=>z(null));e();let n=window.setInterval(e,6e4);return()=>window.clearInterval(n)},[t]),(0,Y.useEffect)(()=>{let e=window.setInterval(()=>B(e=>e+1),3e3);return()=>window.clearInterval(e)},[]);let V=L?.price??u?.last?.close??null;async function H(n,o=``){if(V!=null){j(!0);try{await xe({symbol:e,market:t,kind:n>=V?`price_above`:`price_below`,value:n,note:o}),f.success(`Alert set: ${e} ${n>=V?`≥`:`≤`} ${r(n,N)}`),T(null),i()}catch(e){f.error(a(e))}finally{j(!1)}}}let U=(e,t,n,r)=>(0,X.jsxs)(`button`,{type:`button`,"aria-pressed":e,onClick:n,className:m(`inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium`,e?`border-accent bg-accent-soft text-fg`:`border-line text-muted hover:text-fg`),children:[r&&(0,X.jsx)(`span`,{className:`h-2 w-2 rounded-full`,style:{background:r}}),t]},t),W=(e,t)=>e.includes(t)?e.filter(e=>e!==t):[...e,t];return(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[minmax(0,1fr)_300px]`,children:[(0,X.jsx)(x,{children:(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,X.jsx)(b,{options:ht,value:c.interval,onChange:e=>P({interval:e}),size:`sm`}),(0,X.jsx)(p,{checked:c.live,onChange:e=>P({live:e}),label:(0,X.jsx)(`span`,{className:`text-xs`,children:`Live`})})]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[gt.map(e=>U(c.indicators.includes(e.id),e.label,()=>P({indicators:W(c.indicators,e.id)}),e.id===`supertrend`||e.id===`knn_st`?`linear-gradient(90deg,#34d399 50%,#fb8a8a 50%)`:e.id===`vwma`?`linear-gradient(90deg,#38bdf8 50%,#fbbf24 50%)`:Pe[e.id])),(0,X.jsx)(`span`,{className:`mx-1 w-px bg-line`}),_t.map(e=>U(c.overlays.includes(e.id),e.label,()=>P({overlays:W(c.overlays,e.id)})))]}),(c.indicators.includes(`vwma`)||c.indicators.includes(`knn_st`))&&(0,X.jsxs)(`p`,{className:`rounded-md bg-warn-soft px-3 py-2 text-xs text-warn`,children:[`Experimental nearest-neighbour (kNN) indicators.`,` `,u?.knn&&`kNN now: lean ${u.knn.score>=0?`+`:``}${u.knn.score.toFixed(2)}, agreement ${Math.round(u.knn.agree*100)}%, band ${u.knn.trend}. `,c.indicators.includes(`vwma`)&&`VWMA arrows show each crossover with its kNN vote (faded = the filter would skip it). `,`In our test on 19 large stocks (unseen last 3 of 10 years) both filters did worse than the plain signals, so treat them as something to study, not a signal; test any stock in the Backtest tab.`]}),(0,X.jsx)(St,{status:R,live:c.live?L:null,enabled:c.live,cur:N}),(0,X.jsx)(`div`,{className:`h-[26rem] sm:h-[30rem]`,children:h?(0,X.jsxs)(`div`,{className:`grid h-full place-items-center px-6 text-center text-xs text-muted`,children:[`Chart unavailable: `,h]}):u==null?(0,X.jsx)(A,{className:`h-full w-full`}):u.bars.length===0?(0,X.jsxs)(`div`,{className:`grid h-full place-items-center text-xs text-muted`,children:[`No `,c.interval,` bars for this range.`]}):(0,X.jsx)(Y.Suspense,{fallback:(0,X.jsx)(A,{className:`h-full w-full`}),children:(0,X.jsx)(mt,{data:u,live:L,levels:I,intraday:M,onPick:e=>{T(e),O(e.toFixed(e<1?4:2))}})})}),(0,X.jsx)(`p`,{className:`text-[12px] text-faint`,children:`Click the chart to pick a price for an alert. Crypto streams live from a major exchange; stock prices come from free sources and are about 15 minutes delayed. 1m covers 5 days, 5–30m one month, 1h six months.`})]})}),(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Snapshot`,description:u?`${u.interval} · ${u.period}`:void 0}),(0,X.jsxs)(_,{className:`space-y-3 text-sm`,children:[(0,X.jsx)(Ct,{label:`Last`,value:r(V,N)}),(0,X.jsx)(Ct,{label:`RSI (${u?.interval??``})`,value:o(u?.last?.rsi,1)}),v&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(Ct,{label:`Normal range`,value:`${r(v.normal_low,N)} – ${r(v.normal_high,N)}`}),(0,X.jsx)(Ct,{label:`1-week range`,value:`${r(v.week_low,N)} – ${r(v.week_high,N)}`}),(0,X.jsx)(Ct,{label:`Daily trend`,value:v.trend??`—`}),(0,X.jsx)(`div`,{className:`flex flex-wrap gap-2 pt-1`,children:(0,X.jsx)(E,{size:`sm`,variant:`ghost`,onClick:()=>s({entry:V??void 0}),children:`Size a trade at this price`})})]})]})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Quick alert`,description:`Click the chart or type a price.`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsxs)(`div`,{className:`flex gap-2`,children:[(0,X.jsx)(y,{type:`number`,step:`any`,value:D,onChange:e=>{O(e.target.value);let t=parseFloat(e.target.value);T(Number.isFinite(t)?t:null)},placeholder:V==null?`Price`:String(V.toFixed(2))}),(0,X.jsx)(E,{size:`sm`,loading:k,disabled:C==null||V==null,onClick:()=>C!=null&&H(C),children:`Set`})]}),C!=null&&V!=null&&(0,X.jsxs)(`p`,{className:`text-xs text-muted`,children:[`Alerts when the price `,C>=V?`rises to`:`falls to`,` `,r(C,N),` (`,((C-V)/V*100).toFixed(2),`% from `,r(V,N),`).`]}),u?.pivots&&(0,X.jsx)(`div`,{className:`grid grid-cols-4 gap-1 text-[12px]`,children:Object.entries(u.pivots).map(([e,t])=>(0,X.jsxs)(`button`,{type:`button`,onClick:()=>{T(t),O(t.toFixed(2))},className:`rounded border border-line px-1 py-0.5 text-start hover:border-line-strong`,children:[(0,X.jsx)(`span`,{className:`text-muted`,children:e}),` `,(0,X.jsx)(`span`,{className:`tabular`,children:o(t)})]},e))})]})]})]})]})}function St({status:e,live:t,enabled:n,cur:i}){let[a,o]=(0,Y.useState)(null);if((0,Y.useEffect)(()=>{if(!t||t.direction===`flat`)return;o(t.direction);let e=window.setTimeout(()=>o(null),700);return()=>window.clearTimeout(e)},[t]),!n)return(0,X.jsx)(`div`,{className:`rounded-lg bg-raised px-3 py-2 text-xs text-muted`,children:`Live updates are off. Turn on Live to stream prices.`});let s=t?Math.max(0,Math.round((Date.now()-t.at)/1e3)):null,c=e&&!e.open;return(0,X.jsxs)(`div`,{className:m(`flex flex-wrap items-center gap-x-4 gap-y-1 rounded-lg px-3 py-2 text-xs`,c?`bg-warn-soft text-fg`:`bg-raised text-muted`),children:[(0,X.jsxs)(`span`,{className:`flex items-center gap-1.5 font-medium text-fg`,children:[(0,X.jsx)(`span`,{className:m(`h-2 w-2 rounded-full`,c?`bg-warn`:`animate-pulse bg-up`)}),e?e.always_open?`${e.name} trades 24/7`:e.open?`${e.name} open · closes ${e.next_change_label}`:`${e.name} closed · opens ${e.next_change_label} (${e.session} local)`:`Checking market…`]}),t&&(0,X.jsx)(`span`,{className:m(`tabular rounded px-1.5 py-0.5 font-semibold transition-colors`,a===`up`&&`bg-up-soft text-up`,a===`down`&&`bg-down-soft text-down`,!a&&`text-fg`),children:r(t.price,i)}),(0,X.jsx)(`span`,{children:t?`${t.source===`binance`?`Exchange live`:`Quote stream`} · last tick ${s}s ago · ${t.count} ticks`:`Connecting to the price stream…`}),e&&(0,X.jsxs)(`span`,{children:[`Prices: `,e.delay]}),c&&(0,X.jsx)(`span`,{className:`basis-full text-muted`,children:`The chart shows the last session, so prices won't move until the market reopens. Try a crypto symbol (e.g. BTC-USD) to see live movement now.`})]})}function Ct({label:e,value:t}){return(0,X.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,X.jsx)(`span`,{className:`text-muted`,children:e}),(0,X.jsx)(`span`,{className:`tabular font-medium`,children:t})]})}function wt(e,t){return{symbol:e,market:t,side:`long`,quantity:``,entry_price:``,stop:``,target:``,fees:``,product:t===`india`?`delivery`:``,setup:``,notes:``}}var Tt=[`breakout`,`pullback`,`reversal`,`gap`,`trend`,`range`,`news`];function Et(e){let t=parseFloat(e);return Number.isFinite(t)?t:void 0}function Dt({draft:e,setDraft:t}){let[n,i]=(0,Y.useState)(``),[s,c]=(0,Y.useState)(!1),[l,u]=(0,Y.useState)(null),[d,p]=(0,Y.useState)(null),[h,C]=(0,Y.useState)(!1),[T,O]=(0,Y.useState)({}),[k,j]=(0,Y.useState)(e.symbol),M=(0,Y.useCallback)(()=>{we(n||void 0).then(e=>{u(e),p(null)}).catch(e=>p(a(e)))},[n]);(0,Y.useEffect)(M,[M]),(0,Y.useEffect)(()=>j(e.symbol),[e.symbol]),(0,Y.useEffect)(()=>{l&&!s&&!n&&l.markets.length>1&&i(l.markets[0])},[l,n,s]);async function N(){let n=Et(e.quantity),r=Et(e.entry_price);if(e.symbol&&n&&r){C(!0);try{let i={symbol:e.symbol,market:e.market,side:e.side,quantity:n,entry_price:r,stop:Et(e.stop)??null,target:Et(e.target)??null,fees:Et(e.fees)??null,product:e.market===`india`&&e.product?e.product:null,setup:e.setup,notes:e.notes};await Ce(i),f.success(`Trade logged`),t(wt(e.symbol,e.market)),M()}catch(e){f.error(a(e))}finally{C(!1)}}}async function I(e){let t=Et(T[e.id]??``);if(t)try{await K(e.id,{exit_price:t}),O(t=>{let n={...t};return delete n[e.id],n}),M()}catch(e){f.error(a(e))}}async function L(e){try{await ye(e.id),M()}catch(e){f.error(a(e))}}let z=l?.stats,V=n?Z[n]:void 0,W=n=>t({...e,...n});return(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(`div`,{className:`grid gap-6 xl:grid-cols-[360px_minmax(0,1fr)]`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Log a trade`,icon:`plus`}),(0,X.jsxs)(_,{className:`space-y-3`,children:[(0,X.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,X.jsx)(b,{options:[{value:`long`,label:`Long`},{value:`short`,label:`Short`}],value:e.side,onChange:e=>W({side:e}),size:`sm`})}),(0,X.jsxs)(`div`,{className:`grid grid-cols-[minmax(0,1fr)_120px] gap-2`,children:[(0,X.jsx)(v,{label:`Symbol`,children:(0,X.jsx)(Me,{value:k,onChange:e=>{j(e),W({symbol:e.trim().toUpperCase()})},onSelect:e=>{j(e.symbol),W({symbol:e.symbol,market:e.market})},market:e.market})}),(0,X.jsx)(v,{label:`Market`,children:(0,X.jsx)(g,{options:Ae,value:e.market,onChange:e=>W({market:e.target.value})})})]}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,X.jsx)(v,{label:`Quantity`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:e.quantity,onChange:e=>W({quantity:e.target.value})})}),(0,X.jsx)(v,{label:`Entry price`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:e.entry_price,onChange:e=>W({entry_price:e.target.value})})}),(0,X.jsx)(v,{label:`Stop`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:e.stop,onChange:e=>W({stop:e.target.value})})}),(0,X.jsx)(v,{label:`Target`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:e.target,onChange:e=>W({target:e.target.value})})}),e.market===`india`&&(0,X.jsx)(v,{label:`Product`,children:(0,X.jsx)(g,{options:[{value:`intraday`,label:`Intraday`},{value:`delivery`,label:`Delivery`},{value:`futures`,label:`Futures`},{value:`options`,label:`Options`}],value:e.product||`delivery`,onChange:e=>W({product:e.target.value})})}),(0,X.jsx)(v,{label:`Charges / fees`,hint:`Empty = estimated automatically`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:e.fees,placeholder:`auto`,onChange:e=>W({fees:e.target.value})})}),(0,X.jsxs)(v,{label:`Setup`,children:[(0,X.jsx)(y,{list:`setups`,value:e.setup,onChange:e=>W({setup:e.target.value}),placeholder:`breakout`}),(0,X.jsx)(`datalist`,{id:`setups`,children:Tt.map(e=>(0,X.jsx)(`option`,{value:e},e))})]})]}),(0,X.jsx)(v,{label:`Notes`,children:(0,X.jsx)(y,{value:e.notes,onChange:e=>W({notes:e.target.value}),placeholder:`Why this trade, what you saw`})}),(0,X.jsx)(E,{onClick:N,loading:h,disabled:!e.symbol||!e.quantity||!e.entry_price,children:`Save open trade`}),(0,X.jsx)(`p`,{className:`text-xs text-muted`,children:`Close it later from the list with the exit price. P&L and R-multiple are computed.`})]})]}),(0,X.jsxs)(`div`,{className:`space-y-6`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,X.jsx)(`span`,{className:`text-sm font-medium`,children:`Performance`}),(0,X.jsx)(g,{className:`w-44`,options:[{value:``,label:`All markets`},...(l?.markets??[]).map(e=>({value:e,label:ke(Ae,e)}))],value:n,onChange:e=>{c(!0),i(e.target.value)}})]}),d?(0,X.jsx)(`p`,{className:`text-sm text-down`,children:d}):z?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-line bg-line sm:grid-cols-4`,children:[(0,X.jsx)(Q,{label:`Net P&L`,value:r(z.total_pnl,V),tone:z.total_pnl>=0?`up`:`down`}),(0,X.jsx)(Q,{label:`Win rate`,value:z.win_rate==null?`—`:`${z.win_rate}%`,sub:`${z.wins} W / ${z.losses} L`}),(0,X.jsx)(Q,{label:`Profit factor`,value:o(z.profit_factor),sub:`gross win ÷ gross loss`}),(0,X.jsx)(Q,{label:`Avg R`,value:z.avg_r==null?`—`:`${z.avg_r}R`,sub:`profit ÷ risk taken`}),(0,X.jsx)(Q,{label:`Expectancy`,value:r(z.expectancy,V),sub:`avg per trade`}),(0,X.jsx)(Q,{label:`Avg win / loss`,value:`${r(z.avg_win,V)} / ${r(z.avg_loss,V)}`}),(0,X.jsx)(Q,{label:`Best / worst`,value:`${r(z.best,V)} / ${r(z.worst,V)}`}),(0,X.jsx)(Q,{label:`Losing streak`,value:String(z.max_losing_streak),sub:`${z.open} open`})]}),!n&&(l?.markets.length??0)>1&&(0,X.jsx)(`p`,{className:`text-xs text-warn`,children:`Totals mix currencies; pick a market for exact figures.`}),z.equity.length>1&&(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Equity curve`,description:`Cumulative net P&L of closed trades`}),(0,X.jsx)(_,{children:(0,X.jsx)(`div`,{className:`h-48`,children:(0,X.jsx)(U,{width:`100%`,height:`100%`,children:(0,X.jsxs)(P,{data:z.equity,margin:{top:4,right:4,bottom:0,left:0},children:[(0,X.jsx)(H,{stroke:`var(--color-line)`,vertical:!1}),(0,X.jsx)(R,{dataKey:`date`,tickFormatter:e=>new Date(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`}),tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1,minTickGap:30}),(0,X.jsx)(B,{orientation:`right`,width:60,tick:{fill:`var(--color-faint)`,fontSize:11},axisLine:!1,tickLine:!1}),(0,X.jsx)(F,{contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},labelFormatter:e=>new Date(String(e)).toLocaleString(),formatter:e=>[r(Number(e),V),`Equity`]}),(0,X.jsx)(ee,{type:`monotone`,dataKey:`pnl`,stroke:z.total_pnl>=0?`var(--color-up)`:`var(--color-down)`,fill:z.total_pnl>=0?`var(--color-up)`:`var(--color-down)`,fillOpacity:.12,strokeWidth:1.75})]})})})})]}),z.by_setup.length>0&&(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`By setup`,description:`Which setups actually make money`}),(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`border-y border-line text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-5 py-2 text-start font-medium`,children:`Setup`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Trades`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Win rate`}),(0,X.jsx)(`th`,{className:`px-5 py-2 text-end font-medium`,children:`Net P&L`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:z.by_setup.map(e=>(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`td`,{className:`px-5 py-2`,children:e.setup}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:e.trades}),(0,X.jsxs)(`td`,{className:`tabular px-3 py-2 text-end`,children:[e.win_rate,`%`]}),(0,X.jsx)(`td`,{className:m(`tabular px-5 py-2 text-end`,e.pnl>=0?`text-up`:`text-down`),children:r(e.pnl,V)})]},e.setup))})]})]})]}):(0,X.jsx)(A,{className:`h-40 w-full`})]})]}),(0,X.jsxs)(x,{className:`overflow-hidden`,children:[(0,X.jsx)(w,{title:`Trades`,description:l?`${l.trades.length} shown`:void 0}),l&&l.trades.length===0?(0,X.jsx)(D,{icon:`pencil`,title:`No trades logged`,description:`Log one above, or from the Position size tab.`}):(0,X.jsx)(`div`,{className:`overflow-x-auto`,children:(0,X.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,X.jsx)(`thead`,{className:`border-y border-line text-xs text-muted`,children:(0,X.jsxs)(`tr`,{children:[(0,X.jsx)(`th`,{className:`px-4 py-2 text-start font-medium`,children:`Date`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-start font-medium`,children:`Stock`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Qty`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Entry`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Stop / target`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`Exit`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`P&L`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-end font-medium`,children:`R`}),(0,X.jsx)(`th`,{className:`px-3 py-2 text-start font-medium`,children:`Setup`}),(0,X.jsx)(`th`,{className:`px-4 py-2`})]})}),(0,X.jsx)(`tbody`,{className:`divide-y divide-line`,children:(l?.trades??[]).map(e=>{let t=Z[e.market],n=e.exit_price==null;return(0,X.jsxs)(`tr`,{className:`align-top`,children:[(0,X.jsx)(`td`,{className:`px-4 py-2 text-xs whitespace-nowrap text-muted`,children:new Date(e.entry_at).toLocaleDateString()}),(0,X.jsxs)(`td`,{className:`px-3 py-2`,children:[(0,X.jsx)(`span`,{className:`font-mono font-medium`,children:e.symbol}),(0,X.jsx)(`span`,{className:m(`ms-1.5 text-[12px] font-medium uppercase`,e.side===`long`?`text-up`:`text-down`),children:e.side}),e.notes&&(0,X.jsx)(`div`,{className:`max-w-56 truncate text-xs text-muted`,title:e.notes,children:e.notes})]}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:o(e.quantity,e.quantity%1?4:0)}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:r(e.entry_price,t)}),(0,X.jsxs)(`td`,{className:`tabular px-3 py-2 text-end text-xs text-muted whitespace-nowrap`,children:[r(e.stop,t),` / `,r(e.target,t)]}),(0,X.jsx)(`td`,{className:`px-3 py-2 text-end`,children:n?(0,X.jsxs)(`div`,{className:`flex justify-end gap-1`,children:[(0,X.jsx)(y,{type:`number`,step:`any`,value:T[e.id]??``,onChange:t=>O(n=>({...n,[e.id]:t.target.value})),onKeyDown:t=>t.key===`Enter`&&I(e),placeholder:`Exit`,className:`w-24`}),(0,X.jsx)(E,{size:`sm`,variant:`secondary`,disabled:!T[e.id],onClick:()=>I(e),children:`Close`})]}):(0,X.jsx)(`span`,{className:`tabular`,children:r(e.exit_price,t)})}),(0,X.jsxs)(`td`,{className:m(`tabular px-3 py-2 text-end`,e.pnl!=null&&(e.pnl>=0?`text-up`:`text-down`)),children:[n?(0,X.jsx)(`span`,{className:`text-xs text-muted`,children:`open`}):r(e.pnl,t),e.fees>0&&(0,X.jsxs)(`div`,{className:`text-[12px] text-faint`,title:e.fees_auto?`Estimated from the charges schedule`:`Entered by you`,children:[`fees `,r(e.fees,t),e.fees_auto?` est.`:``]})]}),(0,X.jsx)(`td`,{className:`tabular px-3 py-2 text-end`,children:e.r_multiple==null?`—`:`${e.r_multiple}R`}),(0,X.jsx)(`td`,{className:`px-3 py-2 text-xs text-muted`,children:e.setup||`—`}),(0,X.jsx)(`td`,{className:`px-4 py-2 text-end`,children:(0,X.jsx)(`button`,{type:`button`,onClick:()=>L(e),className:`rounded-md p-1.5 text-faint hover:bg-down-soft hover:text-down`,"aria-label":`Delete ${e.symbol} trade`,children:(0,X.jsx)(S,{name:`trash`})})})]},e.id)})})]})})]})]})}var Ot=`marketmyna.sizer`,kt=[{value:`intraday`,label:`Intraday`},{value:`delivery`,label:`Delivery`},{value:`futures`,label:`Futures`},{value:`options`,label:`Options`}];function At(){let e={capital:`100000`,riskPct:`1`,leverage:`1`,product:`intraday`,pct:`0`,flat:`0`};try{return{...e,...JSON.parse(localStorage.getItem(Ot)??`{}`)}}catch{return e}}function jt({symbol:e,market:t,plan:n,onLog:i}){let[s,c]=(0,Y.useState)(At),[l,u]=(0,Y.useState)(`long`),[d,p]=(0,Y.useState)(``),[m,h]=(0,Y.useState)(``),[g,S]=(0,Y.useState)(``),C=Z[t],T=t===`india`,D=t===`crypto`,k=T&&(s.product===`futures`||s.product===`options`),[A,j]=(0,Y.useState)(``),[M,P]=(0,Y.useState)({stop:null,target:null});(0,Y.useEffect)(()=>{j(``),k&&de(e).then(e=>e&&j(String(e))).catch(()=>{})},[e,k]);function F(e){c(t=>{let n={...t,...e};try{localStorage.setItem(Ot,JSON.stringify(n))}catch{}return n})}(0,Y.useEffect)(()=>{n?(n.entry&&p(n.entry.toFixed(2)),n.stop&&h(n.stop.toFixed(2)),n.target&&S(n.target.toFixed(2)),n.entry&&n.stop&&u(n.stop<n.entry?`long`:`short`)):(p(``),h(``),S(``),N(e,t).then(e=>e.price&&p(e.price.toFixed(2))).catch(()=>{}))},[e,t,n]);let I=(0,Y.useMemo)(()=>{let e=parseFloat(s.capital),t=parseFloat(s.riskPct),n=Math.max(1,parseFloat(s.leverage)||1),r=parseFloat(d),i=parseFloat(m),a=parseFloat(g);if(![e,t,r,i].every(Number.isFinite)||e<=0||r<=0)return null;let o=l===`long`?r-i:i-r;if(o<=0)return{error:l===`long`?`For a long trade the stop must be below entry.`:`For a short trade the stop must be above entry.`};let c=e*t/100,u=k?Math.max(1,parseInt(A,10)||1):1,f=e=>D?Math.floor(e*1e6)/1e6:Math.floor(e/u)*u,p=f(c/o),h=f(e*n/r),_=Math.min(p,h),v=Number.isFinite(a)&&(l===`long`?a>r:a<r);return{qty:_,lotSize:u,limitedByCapital:h<p,value:_*r,riskBudget:c,perShare:o,grossLoss:(l===`long`?i-r:r-i)*_,grossProfit:v?(l===`long`?a-r:r-a)*_:null,rr:v?Math.abs(a-r)/o:null,pctCapital:_*r/e*100,target:v?a:null,entry:r,stop:i}},[s,d,m,g,l,D,k,A]),L=I&&!(`error`in I)?I:null;(0,Y.useEffect)(()=>{if(!L||!L.qty){P({stop:null,target:null});return}let e=e=>Se({market:t,product:T?s.product:void 0,buy_value:(l===`long`?L.entry:e)*L.qty,sell_value:(l===`long`?e:L.entry)*L.qty,quantity:L.qty,commission_pct:parseFloat(s.pct)||0,flat:parseFloat(s.flat)||0}),n=window.setTimeout(()=>{Promise.all([e(L.stop),L.target==null?Promise.resolve(null):e(L.target)]).then(([e,t])=>P({stop:e,target:t})).catch(()=>P({stop:null,target:null}))},250);return()=>window.clearTimeout(n)},[L?.qty,L?.entry,L?.stop,L?.target,l,t,T,s.product,s.pct,s.flat]);async function R(){if(!(!I||`error`in I))try{await xe({symbol:e,market:t,kind:l===`long`?`price_below`:`price_above`,value:I.stop,note:`Stop for ${o(I.qty,D?4:0)} ${e}`}),I.target&&await xe({symbol:e,market:t,kind:l===`long`?`price_above`:`price_below`,value:I.target,note:`Target for ${o(I.qty,D?4:0)} ${e}`}),f.success(I.target?`Stop and target alerts set`:`Stop alert set`)}catch(e){f.error(a(e))}}let z=L,B=M.target??M.stop,V=z&&M.stop?z.grossLoss-M.stop.total:null,H=z&&z.grossProfit!=null&&M.target?z.grossProfit-M.target.total:null,U=z&&z.qty&&M.stop?z.entry+(l===`long`?1:-1)*M.stop.total/z.qty:null;return(0,X.jsxs)(`div`,{className:`grid gap-6 lg:grid-cols-2`,children:[(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Position size`,description:`${e} · risk-based sizing`}),(0,X.jsxs)(_,{className:`space-y-4`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,X.jsx)(b,{options:[{value:`long`,label:`Long (buy)`},{value:`short`,label:`Short (sell)`}],value:l,onChange:e=>u(e),size:`sm`}),T&&(0,X.jsx)(b,{options:kt,value:s.product,onChange:e=>F({product:e}),size:`sm`})]}),(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-3 sm:grid-cols-3`,children:[(0,X.jsx)(v,{label:`Capital (${C})`,children:(0,X.jsx)(y,{type:`number`,value:s.capital,onChange:e=>F({capital:e.target.value})})}),(0,X.jsx)(v,{label:`Risk per trade %`,children:(0,X.jsx)(y,{type:`number`,step:`0.1`,value:s.riskPct,onChange:e=>F({riskPct:e.target.value})})}),(0,X.jsx)(v,{label:`Leverage ×`,children:(0,X.jsx)(y,{type:`number`,step:`0.5`,min:`1`,value:s.leverage,onChange:e=>F({leverage:e.target.value})})}),(0,X.jsx)(v,{label:`Entry`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:d,onChange:e=>p(e.target.value)})}),(0,X.jsx)(v,{label:`Stop loss`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:m,onChange:e=>h(e.target.value)})}),(0,X.jsx)(v,{label:`Target (optional)`,children:(0,X.jsx)(y,{type:`number`,step:`any`,value:g,onChange:e=>S(e.target.value)})}),k&&(0,X.jsx)(v,{label:`Lot size`,hint:`From the exchange's current instrument list`,children:(0,X.jsx)(y,{type:`number`,min:`1`,value:A,onChange:e=>j(e.target.value)})})]}),s.product===`options`&&T&&(0,X.jsx)(`p`,{className:`text-xs text-muted`,children:`For options, enter the premium as entry, stop and target.`}),!T&&(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,X.jsx)(v,{label:`Commission % per side`,children:(0,X.jsx)(y,{type:`number`,step:`0.01`,value:s.pct,onChange:e=>F({pct:e.target.value})})}),(0,X.jsx)(v,{label:`Flat fee per order (${C})`,children:(0,X.jsx)(y,{type:`number`,step:`0.01`,value:s.flat,onChange:e=>F({flat:e.target.value})})})]}),(0,X.jsxs)(`p`,{className:`text-xs text-muted`,children:[`Quantity = (capital × risk %) ÷ (entry − stop), capped by capital × leverage`,k?`, in whole lots`:``,`.`,T&&` Charges use a discount-broker schedule (STT, exchange, SEBI, stamp duty, GST); your contract note is final.`,(t===`us`||t===`global`)&&` US charges include the SEC fee and FINRA TAF on sells.`]})]})]}),(0,X.jsxs)(x,{children:[(0,X.jsx)(w,{title:`Result`}),(0,X.jsx)(_,{className:`space-y-4`,children:I&&`error`in I?(0,X.jsx)(O,{tone:`warn`,title:`Check the stop`,children:I.error}):z?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`grid grid-cols-2 gap-px overflow-hidden rounded-lg border border-line bg-line sm:grid-cols-3`,children:[(0,X.jsx)(Mt,{label:`Quantity`,value:o(z.qty,D?4:0),sub:k&&z.lotSize>1?`${z.qty/z.lotSize} lot${z.qty/z.lotSize===1?``:`s`} of ${z.lotSize}`:void 0,big:!0}),(0,X.jsx)(Mt,{label:`Position value`,value:r(z.value,C),sub:`${z.pctCapital.toFixed(1)}% of capital`}),(0,X.jsx)(Mt,{label:`Risk budget`,value:r(z.riskBudget,C),sub:`${r(z.perShare,C)} per unit`}),(0,X.jsx)(Mt,{label:`Loss at stop`,value:r(V??z.grossLoss,C),tone:`down`,sub:V==null?`before charges`:`after charges`}),(0,X.jsx)(Mt,{label:`Profit at target`,value:H==null?z.grossProfit==null?`—`:r(z.grossProfit,C):r(H,C),tone:(H??z.grossProfit??0)>0?`up`:void 0,sub:H==null?z.grossProfit==null?void 0:`before charges`:`after charges`}),(0,X.jsx)(Mt,{label:`Reward : risk`,value:z.rr==null?`—`:`${z.rr.toFixed(2)} : 1`,tone:z.rr==null?void 0:z.rr>=2?`up`:z.rr<1?`down`:void 0})]}),z.limitedByCapital&&(0,X.jsx)(`p`,{className:`text-xs text-warn`,children:`Limited by capital × leverage: the full risk budget isn't used.`}),z.qty===0&&(0,X.jsxs)(`p`,{className:`text-xs text-warn`,children:[`Risk budget is smaller than one `,k?`lot`:`unit`,`'s risk; widen risk % or tighten the stop.`]}),B&&(0,X.jsxs)(`div`,{children:[(0,X.jsxs)(`span`,{className:`mb-1.5 block text-xs font-medium text-muted`,children:[`Charges (`,M.target?`round trip at target`:`round trip at stop`,`, rates `,B.rates_as_of,`)`]}),(0,X.jsxs)(`ul`,{className:`divide-y divide-line rounded-lg border border-line text-sm`,children:[Object.entries(B.parts).filter(([,e])=>e>.004).map(([e,t])=>(0,X.jsxs)(`li`,{className:`flex justify-between px-3 py-1.5`,children:[(0,X.jsx)(`span`,{className:`text-muted`,children:e}),(0,X.jsx)(`span`,{className:`tabular`,children:r(t,C)})]},e)),(0,X.jsxs)(`li`,{className:`flex justify-between px-3 py-1.5 font-medium`,children:[(0,X.jsx)(`span`,{children:`Total`}),(0,X.jsx)(`span`,{className:`tabular`,children:r(B.total,C)})]})]}),U!=null&&(0,X.jsxs)(`p`,{className:`mt-1.5 text-xs text-muted`,children:[`Breakeven after charges: `,r(U,C)]})]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,X.jsx)(E,{size:`sm`,disabled:!z.qty,onClick:()=>i({side:l,quantity:z.qty,entry:z.entry,stop:z.stop,target:z.target??void 0,product:T?s.product:void 0}),children:`Log in journal`}),(0,X.jsxs)(E,{size:`sm`,variant:`secondary`,icon:`bell`,onClick:R,children:[`Alerts at stop`,z.target?` & target`:``]})]})]}):(0,X.jsx)(`p`,{className:`text-sm text-muted`,children:`Enter capital, risk, entry and stop.`})})]})]})}function Mt({label:e,value:t,sub:n,tone:r,big:i}){return(0,X.jsxs)(`div`,{className:`bg-surface px-3 py-2.5`,children:[(0,X.jsx)(`div`,{className:`text-xs text-muted`,children:e}),(0,X.jsx)(`div`,{className:m(`tabular font-semibold`,i?`text-xl`:`text-sm`,r===`up`&&`text-up`,r===`down`&&`text-down`),children:t}),n&&(0,X.jsx)(`div`,{className:`text-[12px] text-faint`,children:n})]})}var Nt=e({default:()=>Ft}),Pt=[{value:`chart`,label:`Chart`},{value:`scanner`,label:`Scanner`},{value:`alerts`,label:`Alerts`},{value:`options`,label:`Options`},{value:`backtest`,label:`Backtest`},{value:`pairs`,label:`Pairs`},{value:`size`,label:`Position size`},{value:`journal`,label:`Journal`},{value:`risk`,label:`Risk`}];function Ft(){let[e,t]=j(),n=e.get(`tab`)??`chart`,r=(e.get(`symbol`)??`RELIANCE`).toUpperCase(),i=e.get(`market`)??`india`,[a,o]=(0,Y.useState)(r),[s,c]=(0,Y.useState)(i),[l,u]=(0,Y.useState)(null),[d,f]=(0,Y.useState)(null),[p,m]=(0,Y.useState)(()=>wt(r,i)),[h,_]=(0,Y.useState)(null);(0,Y.useEffect)(()=>{let e=()=>oe().then(_,()=>_(null));e();let t=window.setInterval(e,6e4);return()=>window.clearInterval(t)},[]);let v=(0,Y.useCallback)(()=>{J().then(u).catch(()=>u([]))},[]);(0,Y.useEffect)(v,[v]),(0,Y.useEffect)(()=>{o(r),c(i),f(null),m(e=>e.quantity?e:wt(r,i))},[r,i]);function y(n){let r=new URLSearchParams(e);for(let[e,t]of Object.entries(n))t&&r.set(e,t);t(r,{replace:!n.symbol})}function x(e,t){let n=e.trim().toUpperCase();n&&y({symbol:n,market:t})}async function S(){if(!a.trim())return;let e=await je(a,s,e=>G(e,`all`,`all`,10));c(e.market),x(e.symbol,e.market)}return(0,X.jsxs)(`div`,{children:[(0,X.jsx)(T,{title:`Trade`,description:`Charts, scanner, alerts, options, backtests, position sizing, journal and daily risk. Read-only: MarketMyna never places orders.`}),(0,X.jsxs)(`div`,{className:`mb-5 flex flex-wrap items-end gap-3`,children:[(0,X.jsx)(`div`,{className:`min-w-0 basis-full sm:max-w-sm sm:flex-1 sm:basis-auto`,children:(0,X.jsx)(Me,{value:a,onChange:o,detect:{current:s,onDetect:c},onSelect:e=>x(e.symbol,e.market),onSubmit:()=>void S(),placeholder:`Symbol, e.g. RELIANCE, AAPL, BTC-USD`})}),(0,X.jsx)(g,{className:`min-w-0 flex-1 sm:w-36 sm:flex-none`,options:Ae,value:s,onChange:e=>c(e.target.value)}),(0,X.jsx)(E,{variant:`secondary`,onClick:()=>void S(),children:`Open`})]}),(0,X.jsx)(`div`,{className:`mb-5 max-w-full overflow-x-auto pb-1`,children:(0,X.jsx)(b,{options:Pt,value:n,onChange:e=>y({tab:e}),size:`sm`})}),h?.status===`stop`&&n!==`risk`&&(0,X.jsx)(`div`,{className:`mb-5`,children:(0,X.jsxs)(O,{tone:`warn`,title:`Daily loss limit hit: stop trading for today`,children:[h.reasons[0],` `,(0,X.jsx)(`button`,{type:`button`,className:`underline`,onClick:()=>y({tab:`risk`}),children:`Open Risk`})]})}),n===`chart`&&(0,X.jsx)(xt,{symbol:r,market:i,alerts:(l??[]).filter(e=>e.symbol===r&&e.market===i),onAlertsChanged:v,onSize:e=>{f(e),y({tab:`size`})}}),n===`scanner`&&(0,X.jsx)(lt,{market:i,onOpen:(e,t)=>y({symbol:e,market:t,tab:`chart`})}),n===`options`&&(0,X.jsx)(Ke,{symbol:r,market:i}),n===`backtest`&&(0,X.jsx)(Ve,{symbol:r,market:i}),n===`pairs`&&(0,X.jsx)(nt,{symbol:r,market:i}),n===`risk`&&(0,X.jsx)(rt,{onStatus:_}),n===`alerts`&&(0,X.jsx)(Re,{symbol:r,market:i,alerts:l,onChanged:v}),n===`size`&&(0,X.jsx)(jt,{symbol:r,market:i,plan:d,onLog:e=>{m({...wt(r,i),side:e.side,quantity:String(e.quantity),entry_price:String(e.entry),stop:String(e.stop),target:e.target==null?``:String(e.target),product:e.product??``}),y({tab:`journal`})}}),n===`journal`&&(0,X.jsx)(Dt,{draft:p,setDraft:m})]})}export{Ft as default,Pe as n,Nt as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,o as n,p as r,s as i,t as a}from"./format-d8InM0Zw.js";import{r as o}from"./index-CKAnq-Or.js";import{a as s,c,i as l,n as u,o as d,r as f,s as p,t as m}from"./lightweight-charts.production-BF2noug5.js";import{n as h}from"./Trade-_CM7HC4H.js";var g=e(t(),1),_=r();function v(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function y({data:e,levels:t,intraday:r,onPick:y,live:b}){let x=(0,g.useRef)(null),[S,C]=(0,g.useState)(null),w=o(),T=(0,g.useRef)(y);T.current=y;let E=(0,g.useRef)(null),D=(0,g.useRef)(null),O=(0,g.useRef)(null);(0,g.useEffect)(()=>{let n=x.current;if(!n||e.bars.length===0)return;let i=v(`--color-up`,`#34d399`),a=v(`--color-down`,`#fb8a8a`),o=v(`--color-faint`,`#8c95aa`),g=v(`--color-line`,`#2a3142`),_=d(n,{autoSize:!0,layout:{background:{type:m.Solid,color:`transparent`},textColor:o,fontSize:11},grid:{vertLines:{visible:!1},horzLines:{color:g}},rightPriceScale:{borderVisible:!1},timeScale:{borderVisible:!1,timeVisible:r,secondsVisible:!1,rightOffset:4},crosshair:{mode:u.Normal}}),y=_.addSeries(l,{upColor:i,downColor:a,borderUpColor:i,borderDownColor:a,wickUpColor:i,wickDownColor:a});if(y.setData(e.bars.map(e=>({time:e.time,open:e.open,high:e.high,low:e.low,close:e.close}))),E.current=y,D.current=e.bars[e.bars.length-1],e.bars.some(e=>e.volume)){let t=_.addSeries(p,{priceFormat:{type:`volume`},priceScaleId:``});t.priceScale().applyOptions({scaleMargins:{top:.82,bottom:0}}),y.priceScale().applyOptions({scaleMargins:{top:.05,bottom:.22}}),t.setData(e.bars.map(e=>({time:e.time,value:e.volume,color:`${e.close>=e.open?i:a}55`})))}for(let[t,n]of Object.entries(e.series)){if(!n.length)continue;let r=t.endsWith(`_up`)?`up`:t.endsWith(`_down`)?`down`:null,l=r===`up`?i:r===`down`?a:h[t]??o,u=_.addSeries(c,{color:l,lineWidth:r?2:1,lineStyle:t.startsWith(`knn_st`)?s.Dashed:s.Solid,priceLineVisible:!1,lastValueVisible:!1,crosshairMarkerVisible:!1});if(r){let t=new Map(n.map(e=>[e.time,e.value]));u.setData(e.bars.map(e=>t.has(e.time)?{time:e.time,value:t.get(e.time)}:{time:e.time}))}else u.setData(n.map(e=>({time:e.time,value:e.value})))}e.markers?.length&&f(y,e.markers.map(e=>{let t=e.kind.startsWith(`buy`),n=e.kind.endsWith(`_skip`);return{time:e.time,position:t?`belowBar`:`aboveBar`,shape:t?`arrowUp`:`arrowDown`,color:`${t?i:a}${n?`66`:``}`,text:e.text}}));for(let e of t)y.createPriceLine({price:e.price,color:e.color,lineWidth:1,lineStyle:e.dashed?s.Dashed:s.Solid,axisLabelVisible:!0,title:e.label});let b=`${e.symbol}|${e.market}|${e.interval}`,S=O.current;S&&S.key===b&&S.range?_.timeScale().setVisibleLogicalRange(S.range):(_.timeScale().fitContent(),r&&e.bars.length>150&&_.timeScale().setVisibleLogicalRange({from:e.bars.length-150,to:e.bars.length+4}));let w=new Map(e.bars.map(e=>[e.time,e]));return _.subscribeCrosshairMove(e=>C(e.time==null?null:w.get(e.time)??null)),_.subscribeClick(e=>{if(!e.point||!T.current)return;let t=y.coordinateToPrice(e.point.y);t!=null&&Number.isFinite(t)&&T.current(Number(t))}),()=>{let e=_.timeScale().getVisibleLogicalRange();O.current={key:b,range:e?{from:e.from,to:e.to}:null},E.current=null,_.remove()}},[e,t,r,w]),(0,g.useEffect)(()=>{let e=E.current,t=D.current;if(!e||!t||!b)return;let n;if(b.bar){if(b.bar.time<t.time)return;n=b.bar.time===t.time?{...b.bar}:b.bar}else n={...t,close:b.price,high:Math.max(t.high,b.price),low:Math.min(t.low,b.price)};try{e.update({time:n.time,open:n.open,high:n.high,low:n.low,close:n.close}),D.current=n}catch{}},[b]);let k=S??e.bars[e.bars.length-1],A=k?(k.close-k.open)/k.open*100:null,j=k?new Date(k.time*1e3).toLocaleString(void 0,{timeZone:`UTC`,...r?{dateStyle:`medium`,timeStyle:`short`}:{dateStyle:`medium`}}):``;return(0,_.jsxs)(`div`,{className:`relative h-full w-full`,children:[k&&(0,_.jsxs)(`div`,{className:`tabular pointer-events-none absolute top-1 start-1 z-10 flex flex-wrap gap-x-3 rounded-md bg-surface/80 px-2 py-1 text-[12px] text-muted backdrop-blur-sm`,children:[(0,_.jsx)(`span`,{children:j}),(0,_.jsxs)(`span`,{children:[`O `,(0,_.jsx)(`b`,{className:`text-fg`,children:n(k.open)})]}),(0,_.jsxs)(`span`,{children:[`H `,(0,_.jsx)(`b`,{className:`text-fg`,children:n(k.high)})]}),(0,_.jsxs)(`span`,{children:[`L `,(0,_.jsx)(`b`,{className:`text-fg`,children:n(k.low)})]}),(0,_.jsxs)(`span`,{children:[`C `,(0,_.jsx)(`b`,{className:`text-fg`,children:n(k.close)})]}),(0,_.jsx)(`span`,{className:A!=null&&A>=0?`text-up`:`text-down`,children:i(A)}),k.volume>0&&(0,_.jsxs)(`span`,{children:[`Vol `,a(k.volume)]})]}),(0,_.jsx)(`div`,{ref:x,className:`h-full w-full`})]})}export{y as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{b as t,n,o as r,p as i,s as a,t as o}from"./format-d8InM0Zw.js";import{D as s,a as c,g as l,i as u,l as d,o as f,y as p}from"./ui-gsFb8B2m.js";import{M as m}from"./index-CKAnq-Or.js";import{p as h}from"./AreaChart-2i67V6Jf.js";import{$ as g,$t as _,A as v,At as y,B as b,Bt as x,C as S,Ct as C,D as ee,Dt as w,F as te,Ft as ne,I as re,It as T,J as E,Kt as D,L as ie,Lt as O,M as ae,P as oe,Pt as se,Q as ce,Qt as le,R as ue,Rt as de,U as fe,Ut as k,Vt as pe,Y as A,Zt as j,b as me,bt as M,c as he,d as N,dt as ge,en as _e,et as ve,f as ye,ft as be,g as xe,gt as Se,h as Ce,i as we,j as P,k as Te,kt as F,l as Ee,m as De,mt as Oe,n as ke,p as Ae,q as je,qt as I,r as Me,rt as L,s as Ne,tn as R,u as Pe,ut as Fe,vt as Ie,w as Le,x as Re,yt as ze,z as Be,zt as Ve}from"./LineChart-BaOkD1Ta.js";import{a as He,i as Ue,o as We,s as Ge}from"./BarChart-_yngarVl.js";import{n as Ke,t as z}from"./watchlists-B6YqwUIk.js";var B=e(t());function V(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function H(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?V(Object(n),!0).forEach(function(t){qe(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):V(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function qe(e,t,n){return(t=Je(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Je(e){var t=Ye(e,`string`);return typeof t==`symbol`?t:t+``}function Ye(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function U(){return U=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},U.apply(null,arguments)}var Xe=(e,t,n,r,i,a,o)=>{var s=o.x1,c=o.x2,l=o.y1,u=o.y2;if(i==null||a==null)return null;var d=new ye({x:i,y:a}),f={x:e?i.map(s,{position:`start`})??null:i.rangeMin(),y:n?a.map(l,{position:`start`})??null:a.rangeMin()},p={x:t?i.map(c,{position:`end`})??null:i.rangeMax(),y:r?a.map(u,{position:`end`})??null:a.rangeMax()};return o.ifOverflow===`discard`&&(!d.isInRange(f)||!d.isInRange(p))?null:xe(f,p)},Ze=(e,t)=>B.isValidElement(e)?B.cloneElement(e,t):typeof e==`function`?e(t):B.createElement(ge,U({},t,{className:`recharts-reference-area-rect`}));function Qe(e){var t=ne();return(0,B.useEffect)(()=>(t(De(e)),()=>{t(Ce(e))})),null}function $e(e){var t=e.x1,n=e.x2,r=e.y1,i=e.y2,a=e.className,o=e.shape,s=e.xAxisId,c=e.yAxisId,l=Ae(),u=M(),d=T(e=>E(e,`xAxis`,s,u)),f=T(e=>E(e,`yAxis`,c,u));if(d==null||f==null)return null;var p=I(t),m=I(n),h=I(r),g=I(i);if(!p&&!m&&!h&&!g&&!o)return null;var _=Xe(p,m,h,g,d,f,e);if(!_&&!o)return null;var v=e.ifOverflow===`hidden`?`url(#${l})`:void 0;return B.createElement(b,{zIndex:e.zIndex},B.createElement(j,{className:R(`recharts-reference-area`,a)},Ze(o,H(H({clipPath:v},le(e)),_)),_!=null&&B.createElement(re,U({},_,{lowerWidth:_.width,upperWidth:_.width}),B.createElement(ie,{label:e.label}),e.children)))}var et={ifOverflow:`discard`,xAxisId:0,yAxisId:0,radius:0,fill:`#ccc`,label:!1,fillOpacity:.5,stroke:`none`,strokeWidth:1,zIndex:L.area};function W(e){var t=O(e,et);return B.createElement(B.Fragment,null,B.createElement(Qe,{yAxisId:t.yAxisId,xAxisId:t.xAxisId,ifOverflow:t.ifOverflow,x1:t.x1,x2:t.x2,y1:t.y1,y2:t.y2}),B.createElement($e,t))}W.displayName=`ReferenceArea`;var tt=[`option`];function G(){return G=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},G.apply(null,arguments)}function nt(e,t){if(e==null)return{};var n,r,i=rt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function rt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function K(e){return B.createElement(x,e)}function it(e){var t=e.option,n=nt(e,tt);return typeof t==`string`?B.createElement(P,{option:B.createElement(x,G({type:t},n)),DefaultShape:K,shapeProps:n}):B.createElement(P,{option:t,DefaultShape:K,shapeProps:n})}var at=(e,t,n,r,i,a,o)=>A(e,`xAxis`,t,o),ot=(e,t,n,r,i,a,o)=>ce(e,`xAxis`,t,o),st=(e,t,n,r,i,a,o)=>A(e,`yAxis`,n,o),ct=(e,t,n,r,i,a,o)=>ce(e,`yAxis`,n,o),lt=(e,t,n,r)=>ve(e,`zAxis`,r,!1),ut=(e,t,n,r,i)=>i,dt=(e,t,n,r,i,a)=>a,ft=(e,t,n,r,i,a,o)=>Fe(e,void 0,void 0,o),pt=se([g,ut],(e,t)=>e.filter(e=>e.type===`scatter`).find(e=>e.id===t)),mt=se([ft,at,ot,st,ct,lt,pt,dt],(e,t,n,r,i,a,o,s)=>{var c=e.chartData,l=e.dataStartIndex,u=e.dataEndIndex;if(o!=null){var d=o?.data!=null&&o.data.length>0?o.data:c?.slice(l,u+1);if(d!=null&&t!=null&&r!=null&&n!=null&&i!=null&&n?.length!==0&&i?.length!==0)return jt({displayedData:d,xAxis:t,yAxis:r,zAxis:a,scatterSettings:o,xAxisTicks:n,yAxisTicks:i,cells:s})}}),ht=[`id`],gt=[`onMouseEnter`,`onClick`,`onMouseLeave`],_t=[`animationBegin`,`animationDuration`,`animationEasing`,`hide`,`isAnimationActive`,`legendType`,`lineJointType`,`lineType`,`shape`,`xAxisId`,`yAxisId`,`zAxisId`];function q(e,t){if(e==null)return{};var n,r,i=vt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function vt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function J(){return J=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},J.apply(null,arguments)}function yt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Y(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?yt(Object(n),!0).forEach(function(t){bt(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):yt(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function bt(e,t,n){return(t=xt(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function xt(e){var t=St(e,`string`);return typeof t==`symbol`?t:t+``}function St(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var Ct=e=>{var t=e.dataKey,n=e.name,r=e.fill,i=e.legendType;return[{inactive:e.hide,dataKey:t,type:i,color:r,value:F(n,t),payload:e}]},wt=B.memo(e=>{var t=e.dataKey,n=e.points,r=e.stroke,i=e.strokeWidth,a=e.fill,o=e.name,s=e.hide,c=e.formatter,l=e.tooltipType,u=e.id,d={dataDefinedOnItem:n?.map(e=>e.tooltipPayload),getPosition:e=>{var t;return n==null||(t=n[Number(e)])==null?void 0:t.tooltipPosition},settings:{stroke:r,strokeWidth:i,fill:a,nameKey:void 0,dataKey:t,name:F(o,t),hide:s,type:l,color:a,unit:``,formatter:c,graphicalItemId:u}};return B.createElement(v,{tooltipEntrySettings:d})});function Tt(e){var t=e.points,n=e.props,r=n.line,i=n.lineType,a=n.lineJointType;if(!r)return null;var o=_(n),s=_e(r),c,l;if(i===`joint`)c=t.map(e=>({x:e.cx??null,y:e.cy??null}));else if(i===`fitting`){var u=pe(t),d=u.xmin,f=u.xmax,p=u.a,m=u.b,h=e=>p*e+m;c=[{x:d,y:h(d)},{x:f,y:h(f)}]}var g=Y(Y(Y({},o),{},{fill:`none`,stroke:o&&o.fill},s),{},{points:c});return l=B.isValidElement(r)?B.cloneElement(r,g):typeof r==`function`?r(g):B.createElement(be,J({},g,{type:a})),B.createElement(j,{className:`recharts-scatter-line`,key:`recharts-scatter-line`},l)}function Et(e){var t=e.showLabels,n=e.points,r=e.children,i=Ie(),a=(0,B.useMemo)(()=>n?.map(e=>{var t={x:e.x??0,y:e.y??0,width:e.width,height:e.height,lowerWidth:e.width,upperWidth:e.width};return Y(Y({},t),{},{value:void 0,payload:e.payload,viewBox:t,parentViewBox:i,fill:void 0})}),[i,n]);return B.createElement(oe,{value:t?a:void 0},r)}function Dt(e){var t=e.entry,n=e.index,r=e.shape,i=e.activeShape,a=e.baseProps,o=e.id,s=e.restOfAllOtherProps,c=e.animationElapsedTime,l=e.isAnimating,u=e.isEntrance,d=e.onMouseEnterFromContext,f=e.onMouseLeaveFromContext,p=e.onClickFromContext,m=i!=null&&i!==!1,h=(0,B.useMemo)(()=>{var e=String(n);return t=>m&&fe(t)===e},[m,n]),g=T(h)??!1,_=g&&i!=null&&i!==!1?i:r,v=Y(Y(Y({},a),t),{},{isActive:g,index:n,animationElapsedTime:c,isAnimating:l,isEntrance:u,[C]:String(o)});return B.createElement(b,{zIndex:g?L.activeDot:void 0},B.createElement(j,J({className:`recharts-scatter-symbol`},de(s,t,n),{onMouseEnter:d(t,n),onMouseLeave:f(t,n),onClick:p(t,n)}),B.createElement(it,J({option:_},v))))}function Ot(e){var t=e.points,n=e.allOtherScatterProps,r=e.animationElapsedTime,i=e.isAnimating,a=e.isEntrance,o=n.shape,s=n.activeShape,c=n.dataKey,l=n.id,u=q(n,ht),d=n.onMouseEnter,f=n.onClick,p=n.onMouseLeave,m=q(n,gt),h=He(d,c,l),g=We(p),v=Ue(f,c,l);if(!Ve(t))return null;var y=_(u);return B.createElement(B.Fragment,null,B.createElement(Tt,{points:t,props:u}),t.map((e,t)=>B.createElement(Dt,{key:`symbol-${e?.cx}-${e?.cy}-${e?.size}-${t}`,entry:e,index:t,shape:o,activeShape:s,baseProps:y,id:l,restOfAllOtherProps:m,animationElapsedTime:r,isAnimating:i,isEntrance:a,onMouseEnterFromContext:h,onMouseLeaveFromContext:g,onClickFromContext:v})))}var kt=(e,t)=>e==null?[]:t===1?e.flatMap(e=>e.status===`removed`?[]:[e.next]):e.flatMap(e=>e.status===`removed`?[]:e.status===`matched`?[Y(Y({},e.next),{},{cx:e.next.cx==null?void 0:k(e.prev.cx,e.next.cx,t),cy:e.next.cy==null?void 0:k(e.prev.cy,e.next.cy,t),size:k(e.prev.size,e.next.size,t)})]:[Y(Y({},e.next),{},{size:k(0,e.next.size,t)})]);function At(e){var t=e.previousPointsRef,n=e.props,r=n.points,i=n.isAnimationActive,a=n.animationBegin,o=n.animationDuration,s=n.animationEasing,c=n.animationInterpolateFn,l=Le(),u=l.isAnimating,d=l.handleAnimationStart,f=l.handleAnimationEnd,p=Se();return p==null?null:B.createElement(Et,{showLabels:!u,points:r},B.createElement(S,{animationInput:n,animationIdPrefix:`recharts-scatter-`,items:r,previousItemsRef:t,isAnimationActive:i,animationBegin:a,animationDuration:o,animationEasing:s,onAnimationStart:d,onAnimationEnd:f,animationInterpolateFn:c,animationMatchBy:n.animationMatchBy,layout:p},(e,t,r)=>B.createElement(j,null,B.createElement(Ot,{points:e,allOtherScatterProps:n,showLabels:!u,animationElapsedTime:t,isAnimating:u||t<1,isEntrance:r}))),n.children,B.createElement(te,{label:n.label}))}function jt(e){var t=e.displayedData,n=e.xAxis,r=e.yAxis,i=e.zAxis,a=e.scatterSettings,o=e.xAxisTicks,s=e.yAxisTicks,c=e.cells,l=D(n.dataKey)?a.dataKey:n.dataKey,u=D(r.dataKey)?a.dataKey:r.dataKey,d=i&&i.dataKey,f=i?i.range:je.range,p=f&&f[0],m=n.scale.bandwidth?n.scale.bandwidth():0,h=r.scale.bandwidth?r.scale.bandwidth():0;return t.map((e,t)=>{var f=y(e,l),g=y(e,u),_=!D(d)&&y(e,d)||`-`,v=[{name:D(n.dataKey)?a.name:n.name||String(n.dataKey),unit:n.unit||``,value:f,payload:e,dataKey:l,type:a.tooltipType,graphicalItemId:a.id},{name:D(r.dataKey)?a.name:r.name||String(r.dataKey),unit:r.unit||``,value:g,payload:e,dataKey:u,type:a.tooltipType,graphicalItemId:a.id}];_!==`-`&&i!=null&&v.push({name:i.name||i.dataKey,unit:i.unit||``,value:_,payload:e,dataKey:d,type:a.tooltipType,graphicalItemId:a.id});var b=w({axis:n,ticks:o,bandSize:m,entry:e,index:t,dataKey:l}),x=w({axis:r,ticks:s,bandSize:h,entry:e,index:t,dataKey:u}),S=_!==`-`&&i!=null?i.scale.map(_):p,C=S==null?0:Math.sqrt(Math.max(S,0)/Math.PI);return Y(Y({},e),{},{cx:b,cy:x,x:b==null?void 0:b-C,y:x==null?void 0:x-C,width:2*C,height:2*C,size:S,node:{x:f,y:g,z:_},tooltipPayload:v,tooltipPosition:{x:b,y:x},payload:e},c&&c[t]&&c[t].props)})}var Mt=(e,t,n)=>({x:e.cx,y:e.cy,value:Number(n===`x`?e.node.x:e.node.y),errorVal:y(e,t)});function Nt(e){var t=e.hide,n=e.points,r=e.className,i=e.needClip,a=e.xAxisId,o=e.yAxisId,s=e.id,c=(0,B.useRef)(null);if(t)return null;var l=R(`recharts-scatter`,r),u=s;return B.createElement(b,{zIndex:e.zIndex},B.createElement(j,{className:l,clipPath:i?`url(#clipPath-${u})`:void 0,id:s},i&&B.createElement(`defs`,null,B.createElement(Ne,{clipPathId:u,xAxisId:a,yAxisId:o})),B.createElement(Ee,{xAxisId:a,yAxisId:o,data:n,dataPointFormatter:Mt,errorBarOffset:0},B.createElement(j,{key:`recharts-scatter-symbols`},B.createElement(At,{props:e,previousPointsRef:c})))))}var Pt={xAxisId:0,yAxisId:0,zAxisId:0,label:!1,line:!1,legendType:`circle`,lineType:`joint`,lineJointType:`linear`,shape:`circle`,hide:!1,isAnimationActive:`auto`,animationBegin:0,animationDuration:400,animationEasing:`linear`,animationMatchBy:ee,animationInterpolateFn:kt,zIndex:L.scatter};function Ft(e){var t=O(e,Pt),n=t.animationBegin,r=t.animationDuration,i=t.animationEasing,a=t.hide,o=t.isAnimationActive,s=t.legendType,c=t.lineJointType,l=t.lineType,u=t.shape,d=t.xAxisId,f=t.yAxisId,p=t.zAxisId,m=q(t,_t),h=he(d,f).needClip,g=(0,B.useMemo)(()=>ae(e.children,Ge),[e.children]),_=M(),v=T(t=>mt(t,d,f,p,e.id,g,_));return h==null||v==null?null:B.createElement(B.Fragment,null,B.createElement(wt,{dataKey:e.dataKey,points:v,stroke:e.stroke,strokeWidth:e.strokeWidth,fill:e.fill,name:e.name,hide:e.hide,formatter:e.formatter,tooltipType:e.tooltipType,id:e.id}),B.createElement(Nt,J({},m,{xAxisId:d,yAxisId:f,zAxisId:p,lineType:l,lineJointType:c,legendType:s,shape:u,hide:a,isAnimationActive:o,animationBegin:n,animationDuration:r,animationEasing:i,points:v,needClip:h})))}function It(e){var t=O(e,Pt),n=M();return B.createElement(Re,{id:t.id,type:`scatter`},e=>B.createElement(B.Fragment,null,B.createElement(Te,{legendPayload:Ct(t)}),B.createElement(me,{type:`scatter`,id:e,data:t.data,xAxisId:t.xAxisId,yAxisId:t.yAxisId,zAxisId:t.zAxisId,dataKey:t.dataKey,hide:t.hide,name:t.name,tooltipType:t.tooltipType,isPanorama:n}),B.createElement(Ft,J({},t,{id:e}))))}var X=B.memo(It,Oe);X.displayName=`Scatter`;var Lt=[`item`],Rt=(0,B.forwardRef)((e,t)=>B.createElement(ke,{chartName:`ScatterChart`,defaultTooltipEventType:`item`,validateTooltipEventTypes:Lt,tooltipPayloadSearcher:Be,categoricalChartProps:e,ref:t})),Z=i();function zt({symbol:e,market:t}){let[i,d]=(0,B.useState)(null),[m,g]=(0,B.useState)(null),[_,v]=(0,B.useState)(`insiders`);(0,B.useEffect)(()=>{let r=!0;return d(null),g(null),h(e,t).then(e=>r&&d(e)).catch(e=>r&&g(n(e))),()=>{r=!1}},[e,t]);let y=i?.breakdown,b=i?.insiders,x=[{value:`insiders`,label:`Insider trades${b?` · ${b.recent.length}`:``}`},...i?.institutions.length?[{value:`institutions`,label:`Institutions`}]:[],...i?.funds.length?[{value:`funds`,label:`Funds`}]:[],...i?.deals?[{value:`deals`,label:`Bulk / block deals · ${i.deals.count}`}]:[]];return(0,Z.jsxs)(u,{id:`section-ownership`,section:`Ownership`,children:[(0,Z.jsx)(f,{title:`Ownership & insiders`,description:`Who holds the shares, and whether insiders are buying or selling`}),(0,Z.jsxs)(c,{className:`space-y-4`,children:[m&&(0,Z.jsx)(`p`,{className:`text-sm text-muted`,children:m}),!i&&!m&&(0,Z.jsx)(p,{className:`h-32 w-full`}),i&&y&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`div`,{className:`grid grid-cols-2 gap-3 sm:grid-cols-4`,children:[(0,Z.jsx)(Q,{label:`Insiders / promoters`,value:y.insiders_pct==null?`—`:`${r(y.insiders_pct,1)}%`}),(0,Z.jsx)(Q,{label:`Institutions`,value:y.institutions_pct==null?`—`:`${r(y.institutions_pct,1)}%`}),(0,Z.jsx)(Q,{label:`Free float`,value:o(y.float_shares),sub:`shares`}),(0,Z.jsx)(Q,{label:`Insiders, ${b?.days??180}d`,value:b?.bias?b.bias===`net buying`?`Net buying`:`Net selling`:`No trades`,className:b?.bias===`net buying`?`text-up`:b?.bias===`net selling`?`text-down`:void 0,sub:b&&(b.buys||b.sells)?`${b.buys} buys · ${b.sells} sells`:void 0})]}),i.short&&(0,Z.jsxs)(`div`,{className:`rounded-lg bg-canvas px-3 py-2 text-sm`,children:[(0,Z.jsxs)(`div`,{className:`text-xs font-medium text-muted`,children:[`Short interest`,i.short.as_of?` · as of ${i.short.as_of}`:``]}),(0,Z.jsxs)(`div`,{className:`mt-1 flex flex-wrap gap-x-6 gap-y-1`,children:[(0,Z.jsxs)(`span`,{children:[o(i.short.shares),` shares short`]}),(0,Z.jsxs)(`span`,{children:[i.short.pct_of_float==null?`—`:`${r(i.short.pct_of_float,2)}%`,` of float`]}),(0,Z.jsxs)(`span`,{title:`Days of average volume needed to buy back every short share`,children:[r(i.short.days_to_cover,1),` days to cover`]}),i.short.change_pct!=null&&(0,Z.jsxs)(`span`,{className:i.short.change_pct>0?`text-down`:`text-up`,children:[a(i.short.change_pct,1),` vs last month`]})]})]}),(0,Z.jsx)(l,{size:`sm`,value:_,onChange:e=>v(e),options:x}),_===`insiders`&&(b&&b.recent.length?(0,Z.jsx)(`ul`,{className:`divide-y divide-line text-sm`,children:b.recent.map((e,t)=>(0,Z.jsxs)(`li`,{className:`flex items-start justify-between gap-3 py-1.5`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsxs)(`div`,{className:`truncate`,children:[e.insider,` `,(0,Z.jsxs)(`span`,{className:`text-xs text-faint`,children:[`· `,e.position]})]}),(0,Z.jsxs)(`div`,{className:`truncate text-[12px] text-faint`,children:[e.date,` · `,e.text||`—`]})]}),(0,Z.jsxs)(`div`,{className:`shrink-0 text-end`,children:[(0,Z.jsx)(`div`,{className:s(`text-xs font-medium uppercase`,e.side===`buy`?`text-up`:e.side===`sell`?`text-down`:`text-muted`),children:e.side}),(0,Z.jsxs)(`div`,{className:`tabular text-[12px] text-faint`,children:[o(e.shares),` sh`,e.value?` · ${o(e.value)}`:``]})]})]},t))}):(0,Z.jsxs)(`p`,{className:`text-sm text-muted`,children:[`No insider trades reported in the last `,b?.days??180,` days.`]})),_===`institutions`&&(0,Z.jsx)(Bt,{rows:i.institutions}),_===`funds`&&(0,Z.jsx)(Bt,{rows:i.funds}),_===`deals`&&i.deals&&(0,Z.jsx)(Vt,{deals:i.deals,showSymbol:!1}),(0,Z.jsx)(`p`,{className:`text-[12px] text-faint`,children:`From exchange and regulatory filings; coverage outside the US is thinner.`})]})]})]})}function Q({label:e,value:t,sub:n,className:r}){return(0,Z.jsxs)(`div`,{className:`rounded-lg bg-canvas px-3 py-2`,children:[(0,Z.jsx)(`div`,{className:`text-[12px] text-faint`,children:e}),(0,Z.jsx)(`div`,{className:s(`tabular text-sm font-semibold`,r),children:t}),n&&(0,Z.jsx)(`div`,{className:`text-[11px] text-faint`,children:n})]})}function Bt({rows:e}){return(0,Z.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,Z.jsx)(`thead`,{className:`text-xs text-muted`,children:(0,Z.jsxs)(`tr`,{children:[(0,Z.jsx)(`th`,{className:`py-1 text-start font-medium`,children:`Holder`}),(0,Z.jsx)(`th`,{className:`py-1 text-end font-medium`,children:`% held`}),(0,Z.jsx)(`th`,{className:`py-1 text-end font-medium`,children:`Change`})]})}),(0,Z.jsx)(`tbody`,{className:`divide-y divide-line`,children:e.map(e=>(0,Z.jsxs)(`tr`,{title:e.reported?`Reported ${e.reported}`:void 0,children:[(0,Z.jsx)(`td`,{className:`max-w-0 truncate py-1.5 pe-2`,children:e.holder}),(0,Z.jsx)(`td`,{className:`tabular py-1.5 pe-2 text-end`,children:e.pct_held==null?`—`:`${r(e.pct_held*100,2)}%`}),(0,Z.jsx)(`td`,{className:s(`tabular py-1.5 text-end`,(e.pct_change??0)>=0?`text-up`:`text-down`),children:e.pct_change==null?`—`:a(e.pct_change*100,1)})]},e.holder))})]})}function Vt({deals:e,showSymbol:t}){let[n,i]=(0,B.useState)(!1);return e.deals.length?(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`ul`,{className:`divide-y divide-line text-sm`,children:e.deals.slice(0,n?150:15).map((e,n)=>(0,Z.jsxs)(`li`,{className:`flex items-start justify-between gap-3 py-1.5`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsxs)(`div`,{className:`truncate`,children:[t&&(0,Z.jsx)(`span`,{className:`me-2 font-mono`,children:e.symbol}),e.client]}),(0,Z.jsxs)(`div`,{className:`truncate text-[12px] text-faint`,children:[e.date,` · `,e.kind,` deal`,e.remarks?` · ${e.remarks}`:``]})]}),(0,Z.jsxs)(`div`,{className:`shrink-0 text-end`,children:[(0,Z.jsx)(`div`,{className:s(`text-xs font-medium uppercase`,e.side===`buy`?`text-up`:`text-down`),children:e.side}),(0,Z.jsxs)(`div`,{className:`tabular text-[12px] text-faint`,children:[o(e.qty),` @ `,r(e.price),e.value?` · ₹${o(e.value)}`:``]})]})]},n))}),e.deals.length>15&&(0,Z.jsx)(`button`,{type:`button`,onClick:()=>i(e=>!e),className:`mt-1 text-xs text-accent-fg hover:underline`,children:n?`Show fewer`:`Show all ${e.deals.length}`}),(0,Z.jsx)(`p`,{className:`mt-2 text-[12px] text-faint`,children:`Bulk = over 0.5% of the company's shares in a day; block = a single large trade in the block window. Source: NSE.`})]}):(0,Z.jsxs)(`p`,{className:`text-sm text-muted`,children:[`No bulk or block deals`,e.history_from?` since ${e.history_from}`:``,`. History builds up from the day MarketMyna first collected it.`]})}var $=[`#6d8cff`,`#34d399`,`#fbbf24`,`#f472b6`,`#22d3ee`,`#a78bfa`,`#fb923c`,`#94a3b8`,`#ef4444`,`#10b981`,`#eab308`,`#8b5cf6`,`#06b6d4`,`#f97316`,`#84cc16`],Ht=e=>({leading:{label:`Leading`,note:`Beating the ${e} and still gaining`,className:`text-up`},weakening:{label:`Weakening`,note:`Still ahead but losing steam`,className:`text-warn`},lagging:{label:`Lagging`,note:`Behind the ${e} and still slipping`,className:`text-down`},improving:{label:`Improving`,note:`Behind but catching up`,className:`text-accent-fg`}});function Ut({series:e,focus:t}){let n=(0,B.useMemo)(()=>{let t=e.flatMap(e=>e.tail),n=e=>Math.max(1,...t.map(t=>Math.abs(t[e]-100)))*1.1;return{x:n(`ratio`),y:n(`momentum`)}},[e]);return(0,Z.jsx)(`div`,{className:`h-80`,children:(0,Z.jsx)(ze,{width:`100%`,height:`100%`,children:(0,Z.jsxs)(Rt,{margin:{top:10,right:10,bottom:20,left:0},children:[(0,Z.jsx)(W,{x1:100,x2:100+n.x,y1:100,y2:100+n.y,fill:`var(--color-up)`,fillOpacity:.06}),(0,Z.jsx)(W,{x1:100,x2:100+n.x,y1:100-n.y,y2:100,fill:`var(--color-warn)`,fillOpacity:.06}),(0,Z.jsx)(W,{x1:100-n.x,x2:100,y1:100-n.y,y2:100,fill:`var(--color-down)`,fillOpacity:.06}),(0,Z.jsx)(W,{x1:100-n.x,x2:100,y1:100,y2:100+n.y,fill:`var(--color-accent)`,fillOpacity:.06}),(0,Z.jsx)(Pe,{stroke:`var(--color-line)`}),(0,Z.jsx)(N,{x:100,stroke:`var(--color-line-strong)`}),(0,Z.jsx)(N,{y:100,stroke:`var(--color-line-strong)`}),(0,Z.jsx)(we,{type:`number`,dataKey:`ratio`,domain:[100-n.x,100+n.x],tickFormatter:e=>r(e,1),tick:{fill:`var(--color-faint)`,fontSize:11},label:{value:`Relative strength →`,position:`insideBottom`,offset:-10,fill:`var(--color-faint)`,fontSize:11}}),(0,Z.jsx)(Me,{type:`number`,dataKey:`momentum`,domain:[100-n.y,100+n.y],tickFormatter:e=>r(e,1),width:44,tick:{fill:`var(--color-faint)`,fontSize:11}}),(0,Z.jsx)(ue,{cursor:!1,contentStyle:{background:`var(--color-raised)`,border:`1px solid var(--color-line-strong)`,borderRadius:8,fontSize:12},formatter:(e,t)=>[r(Number(e),2),t===`ratio`?`RS-Ratio`:`RS-Momentum`],labelFormatter:()=>``}),e.map((e,n)=>{let r=t!=null&&t!==e.name,i=$[n%$.length],a=t===e.name?e.tail:e.tail.slice(-1);return(0,Z.jsx)(X,{name:e.name,data:a,line:t===e.name&&{stroke:i,strokeOpacity:.8},fill:i,fillOpacity:r?.15:1,isAnimationActive:!1,shape:e=>{let t=e.index===a.length-1;return(0,Z.jsx)(`circle`,{cx:e.cx,cy:e.cy,r:t?5:2,fill:i,fillOpacity:r?.15:t?1:.6})}},e.name)})]})})})}function Wt({selected:e,icon:t,label:n,onClick:r,rail:i,extra:a}){return(0,Z.jsxs)(`button`,{type:`button`,"aria-current":e?`page`:void 0,onClick:r,className:s(`flex items-center gap-2 whitespace-nowrap rounded-lg text-[13px] font-medium transition-colors`,i?`w-full px-2.5 py-1.5 text-start`:`shrink-0 border px-2.5 py-1.5`,e?s(`bg-accent-soft text-fg`,i?`ring-1 ring-accent/40`:`border-accent/50`):s(`text-muted hover:bg-raised/60 hover:text-fg`,!i&&`border-line`)),children:[(0,Z.jsx)(d,{name:t,className:s(`h-3.5 w-3.5`,e?`text-accent`:`text-faint`)}),n,a&&(0,Z.jsx)(`span`,{className:`ms-auto flex items-center ps-1`,children:a})]})}function Gt({label:e,rail:t,children:n}){return(0,Z.jsxs)(`div`,{className:t?`pt-3`:`flex shrink-0 items-center gap-1.5 border-s border-line ps-1.5`,children:[t&&(0,Z.jsx)(`div`,{className:`px-2.5 pb-1 text-[11px] font-semibold uppercase tracking-wide text-faint`,children:e}),n]})}function Kt({label:e,nav:t,children:n}){return(0,Z.jsxs)(`div`,{className:`lg:grid lg:grid-cols-[13rem_minmax(0,1fr)] lg:gap-6`,children:[(0,Z.jsx)(`nav`,{"aria-label":e,className:`hidden lg:block`,children:(0,Z.jsx)(`div`,{className:`sticky top-4 space-y-0.5`,children:t(!0)})}),(0,Z.jsx)(`nav`,{"aria-label":e,className:`-mx-4 mb-4 flex gap-1.5 overflow-x-auto px-4 pb-1 sm:-mx-6 sm:px-6 lg:hidden`,children:t(!1)}),(0,Z.jsx)(`div`,{className:`min-w-0`,children:n})]})}function qt({item:e,showLabel:t=!1}){let{t:n}=m(`app`),{lists:r,members:i,loaded:a,load:o,add:c,remove:l}=Ke(),[u,f]=(0,B.useState)(!1),[p,h]=(0,B.useState)(!1),g=(0,B.useRef)(null);(0,B.useEffect)(()=>{a||o()},[a,o]),(0,B.useEffect)(()=>{if(!u)return;let e=e=>{g.current&&!g.current.contains(e.target)&&f(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[u]);let _=z(e),v=new Set(i.filter(e=>z(e)===_).map(e=>e.watchlist_id)),y=v.size>0;async function b(t){h(!0);try{v.has(t)?await l(t,e):await c(t,e)}finally{h(!1)}}function x(e){e.stopPropagation(),r.length&&(r.length===1?b(r[0].id):f(e=>!e))}let S=n(y?`watch.watching`:`watch.watch`);return(0,Z.jsxs)(`div`,{ref:g,className:`relative inline-block`,onClick:e=>e.stopPropagation(),children:[(0,Z.jsxs)(`button`,{type:`button`,onClick:x,disabled:p||!a,"aria-pressed":y,"aria-haspopup":r.length>1?`menu`:void 0,title:n(y?`watch.inList`:`watch.add`),className:s(`inline-flex items-center gap-1.5 rounded-md transition-colors disabled:opacity-50`,t?`border border-line-strong bg-raised px-3 py-1.5 text-xs font-medium hover:border-faint`:`p-1`,y?`text-warn`:`text-faint hover:text-fg`),children:[(0,Z.jsx)(d,{name:`star`,className:s(`h-4 w-4`,y&&`fill-current`)}),t&&(0,Z.jsx)(`span`,{className:y?`text-fg`:void 0,children:S})]}),u&&(0,Z.jsxs)(`div`,{role:`menu`,className:`absolute end-0 z-30 mt-1 w-56 rounded-lg border border-line-strong bg-raised py-1 text-start shadow-xl`,children:[(0,Z.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-muted`,children:n(`watch.addTo`,{symbol:e.symbol})}),r.map(e=>(0,Z.jsxs)(`button`,{type:`button`,role:`menuitemcheckbox`,"aria-checked":v.has(e.id),onClick:()=>b(e.id),disabled:p,className:`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-line`,children:[(0,Z.jsx)(`span`,{className:s(`grid h-4 w-4 place-items-center rounded border`,v.has(e.id)?`border-accent bg-accent text-white`:`border-line-strong`),children:v.has(e.id)&&(0,Z.jsx)(d,{name:`check`,className:`h-3 w-3`})}),(0,Z.jsx)(`span`,{className:`truncate`,children:e.name}),(0,Z.jsx)(`span`,{className:`ms-auto text-xs text-faint`,children:e.count})]},e.id))]})]})}export{$ as a,Vt as c,Wt as i,zt as l,Kt as n,Ut as o,Gt as r,Ht as s,qt as t};
|