just messing around - #2
Open
karmataklu-bot wants to merge 174 commits into
Open
Conversation
Updated README to reflect new project structure and features.
- Chrome extension (popup, background, analyse UI) for NEPSE CAGR calculation - Native messaging host (nepse_host.py + wrapper shell script) bridges extension to local Python engine - nepse_cagr_server.py runs local HTTP server for CAGR calculations - com.nepse.cagr.json manifest registers native host with Chrome - CLAUDE.md and SETUP.md document project and setup steps
Updated README to clarify functionality and usage details.
Added a section for the Browser Extension, detailing its architecture, files, and setup instructions for macOS.
Owner
|
Loved your work. Actually there is automation implemented in this CI/CD Pipeline. We can archive your branch in community-chrome-extension branch. Please create P.R in that branch |
added 14 commits
May 7, 2026 08:36
- index_history.py: scrapes all 18 NEPSE indices from ShareSansar - GET request with numeric index_id (not POST with text name) - 30-day chunks (server silently returns 0 rows for >= 31 days) - JSON response parsing (not HTML table) - Incremental mode: resumes from latest CSV date - Query mode: --query --index "X" --date YYYY-MM-DD - run_index_history.py: CLI entry point mirroring run_daily.py pattern - data/index/: initial historical data for all 18 sub-indices
…to fix MV3 CSP Chrome MV3 blocks inline <script> blocks and CDN scripts. - Extract all JS from analyse.html into analyse.js (external file) - Download chart.umd.js locally (was blocked from cdnjs CDN) - Light mode theme toggle now works
- Add topbar-right container to group theme and back buttons - Implement switchPage function for multi-page navigation - Back button shows on non-analyse pages, hidden on main page - Back button navigates back to analyse (main) page - Add corresponding CSS styling for back-btn
SamirWagle
self-requested a review
May 7, 2026 12:08
…nflict - Add asterisk note clarifying NEPSE data based on closing prices - Remove malformed JavaScript code from HTML merge conflict - Clean up CAGR page section
Remove height:0 from Estimated (1994-2000) legend item. Height override prevented dashed border from rendering. Now displays properly as dashed line.
- Add company name/ticker search input field for future filtering capability - Add "My Predictions — Next Cycle Top" section with 4 key indicators: * Buffett Indicator (market cap = GDP) reaching 100% * Daily trading volume approaching 35–40 Arab * Index crossing 5,000 * 4-year cycle milestone from Sep 2022 bottom (~Sep 2026) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…ack nav
- Add page-buffett: full blog-style article from PDF (all 5 pages)
- Include Global & Regional Buffett Indicator comparison table (11 markets)
- Wire #buffett-link click → switchPage('buffett') via JS (CSP-safe)
- Fix back button to return to previous page (bullbear → buffett → back = bullbear)
- Add buffett-indicator.pdf to extension and web_accessible_resources in manifest
- Article width set to 749px, minimal dark aesthetic
added 30 commits
July 27, 2026 10:41
Technical swing/position signal for NEPSE over a 2-week to 3-month horizon, plus a Telegram alarm for stop, target, and time-stop events. scripts/karma_signal.py - Seven hard gates: liquidity, market regime, MA stack, proximity to the 250-day high, extension, ADX, volume expansion. Score ranks survivors only. - Two modes: swing (10-30d, +18%/-8%) and position (20-63d, +40%/-12%). Stops floor at 1.5x/2.5x ATR so they are never tighter than daily noise. - Prices are backward-adjusted for bonus shares and rights. Raw NEPSE series gap 20-50% on ex-dates, which an unadjusted backtest reads as crashes. - Backtest, target/stop grid, and walk-forward split, all net of NEPSE commission, SEBON fee, DP charge, and 7.5% short-term CGT. scripts/karma_alerts.py - Tracks open positions in data/karma_positions.json, checks the latest bar against stored levels, and pushes Telegram alerts. Credentials come from the environment only. - Stale data raises a warning rather than an all-clear, and a bar breaching both stop and target reports the stop. Measured, not claimed. The requested 70% hit rate on a +40% target does not appear anywhere in a 30-config grid; the best is 49.1% at +15%/-15%. Walk-forward at 2023-01-01 shows material regime dependence: position mode nets +7.03% per trade in sample versus +1.02% out of sample, and swing nets +0.19% out of sample, which is noise. Survivorship bias and slippage remain unmodeled.
`size` converts risk-per-trade into position size via the stop width, and prints the losing-streak drawdown at that risk level. Risk per trade and position size are different numbers: a 12% stop turns 1% risk into an 8.3% position. Defaults to 1% risk, 6% total heat, which caps concurrent positions at 6 — the binding constraint on NEPSE, where positions are highly correlated and six names behave as one bet in a drawdown. At the measured 39.6% out-of-sample win rate, 5% risk per trade produces a 40% drawdown on a 10-trade losing streak, needing +67% to recover.
`tiers` slices out-of-sample outcomes by signal score, to check the assumption that better-looking setups win more often. Backtest trades now carry their score and indicator readings so outcomes can be conditioned on them. Result is not a clean edge. Position mode's top score bucket nets +3.03% per trade versus +1.02% overall, but the relationship is non-monotonic: the middle bucket (85-94) nets +0.05%, below the bottom bucket (70-84) at +2.55%. A genuinely predictive score would rank monotonically. Swing mode shows no relationship at all. Recording the tool and the caveat rather than the apparent edge.
Exit change ----------- The default exit is now an uncapped trailing stop (2xATR behind the highest close), not a fixed profit target. This strategy has a set-mining payoff shape: out-of-sample the median trade loses and the mean trade wins, so the large winners are the entire edge. A fixed target truncates exactly those outcomes. Measured out-of-sample, per trade net of costs: position +40% target -> +1.02% | trail 2xATR -> +2.04% swing +18% target -> +0.19% | trail 2xATR -> +1.18% Both modes roughly double, medians shrink, holds shorten. 2xATR won independently in each mode, which is corroboration rather than a fit, but it was still chosen from three candidates on out-of-sample data — treat the exact multiple as provisional and the direction as the finding. `--exit target` restores the old behaviour for comparison. karma_alerts now ratchets each position's stop on every `watch` run and never loosens it. Adds `tail` (capped vs trailing) and `tiers` (does selectivity pay — it does not, the score is non-monotonic) as evidence commands. Index scrape path ----------------- `_auto_detect_data_dir()` walked upward for any folder containing `data`. When `scraper/data/` appeared on 2026-05-04 the walk matched it first, so every index scrape since wrote to `scraper/data/index/` while the app read `data/index/`. Every scrape succeeded; the data was simply invisible, and the market_regime gate spent three months reading a frozen index. Now anchored to the repo root with no search. `run_daily.py` also never called the index scrape at all — now wired in after the price scrape, along with the position-alarm check. Both are failure-isolated and skippable via --skip-index / --skip-alerts.
Every gate in this signal is a long-only trend filter and NEPSE rose across most of the sample, so a positive average trade proves nothing on its own. This adds the test that can actually kill the strategy. Each trade is now paired against the NEPSE return over its exact entry/exit window, which isolates selection and timing from market drift. Buy-and-hold is charged its real costs too (one round trip, 5% long-term CGT) rather than being compared gross against a net strategy. Two findings worth recording: Capacity is not a constraint. 13.6 (swing) and 29.4 (position) positions are open on an average day, so a 6-slot heat cap always fills and the annualized figure does not need an idle-cash haircut. Alpha is not significant. The per-trade t-stat of 2.09 was an artifact of treating dozens of simultaneously-open, market-correlated trades as independent draws. Collapsing to one observation per month drops it to 0.72, and per quarter to 0.32; swing goes negative quarterly. Only 41% of months show positive alpha. The verdict line now refuses to print "beats" below a t-stat of 2.
The benchmark showed higher returns than buy-and-hold with no significance, which leaves the strategy unexplained rather than disproven. This tests one mechanism, with the hypothesis written into the docstring before the first run: a ratcheting stop should earn its keep when the market falls and cost something when it rises. With ~13 independent quarters, a hypothesis invented after seeing the split would be indistinguishable from curve-fitting, so it is committed up front. Confirmed in both modes. Alpha is +2.11% (swing) and +2.59% (position) in windows where NEPSE fell, and -2.16% / -1.50% where it rose; swing's bull-market underperformance is significantly negative at t=-3.16. The two effects roughly cancel, which explains why total alpha tested insignificant. This is a drawdown reducer, not a return generator. Judge it on the equity curve, not the return. Also audited survivorship rather than continuing to assert it: 228 of 261 delisted names already carry full price history, and delisted names are 1% of post-2023 trades. Caveat removed from the docs as overstated.
The spec was two Telegram events — stop loss, and profit target. Replacing
the fixed target with a trailing stop removed the second one entirely:
`_check` was documented "No profit target" and could only fire on a stop or
a time stop. Positions now carry a target again and `watch` alerts on it.
The trailing stop still runs, so a position can exit on the trail before
reaching the target. That is deliberate — capping winners roughly halved net
return — so the target message reports the level was reached, shows where the
trail sits, and leaves the sell decision to the trader.
A bar touching both stop and target reports the stop. `target` is read with
.get() so a position written by an earlier build cannot crash the watcher
that guards every other position.
Scan now defaults to 10 candidates per mode and prints the measured odds:
position 41.9% win, frequency odds 0.72:1 AGAINST, payoff 2.04:1,
money odds 1.47:1 for, EV +2.04%/trade
swing 40.8% win, frequency odds 0.69:1 AGAINST, payoff 1.90:1,
money odds 1.31:1 for, EV +1.19%/trade
Both ratios are printed because quoting either alone misleads: this loses
more often than it wins and profits on win size. Nothing here is 4:1.
The odds are identical across recommended stocks by design — `tiers` showed
score has no monotonic link to outcome, so a per-ticker probability would be
fabricated. Only `rewd:risk` varies, being the name's own ATR stop width.
Three months of index scrapes landed in scraper/data/index/ instead of data/index/ because _auto_detect_data_dir walked upward and matched scraper/data/ (created by company_id_mapping.json on 2026-05-04) before the repo root. Every scrape succeeded, so nothing errored — the app simply kept reading files frozen at 2026-05-06. 954 rows added, 0 removed: purely additive, no existing history rewritten. All 17 live sub-indices now run through 2026-07-27. The `insurance` folder stays at 2018-07-16, which is correct — NEPSE retired that sub-index when it split into life and non-life. The path fix is in 1393003; this is the data it should have been writing.
Recording a trade is not consent to be messaged about it. The workflow is
scan, decide, record the fill and target, and only then arm the alarm — so
positions now start with alerts_enabled false and are armed by hand:
karma_alerts.py open NABIL --entry 560 --target-price 700
karma_alerts.py alerts on NABIL
An unarmed position is still tracked: levels are checked, the stop still
ratchets, and a breach still updates status and prints. It simply sends
nothing. Tracking and notification are separate concerns, and conflating them
trains you to ignore the stream that carries the one alert that mattered.
Arming warns when Telegram is unconfigured, and says explicitly that the
shell it was armed in is not the environment cron runs `watch` in. A silent
credential gap is the failure this project has already been bitten by twice.
Also adds --target-price for an absolute level, which is what you actually
decide at the desk rather than a percentage off a default.
An armed position with no credentials in the environment is the worst state this tool can occupy: it looks guarded and is not. Previously nothing was said until a level actually tripped, and by then the message had nowhere to go — so a quiet run read as "all clear" when nothing could have been delivered. `watch` now checks for credentials before checking any level and warns on stderr naming the armed tickers. This matters most under cron, which does not read an interactive shell's exports: a token set in a terminal makes test-telegram succeed there and changes nothing about the 17:30 run.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I made a brave extension that calcualtes CAR from your data.
If you have time check it out!