Learn / Reading the numbers

What does this metric mean?

Every number here, and how it was worked out

Every statistic in this app, how it is calculated, and what it refuses to claim.

You know your way around a chart of the heavens — zodiac signs, nakshatras and tithis are ordinary words to you. This page assumes nothing at all about statistics. Every idea is built from scratch, and every formula is followed by the same calculation done on real market data.

Correlating planetary positions with prices is easy to do badly. Try thousands of combinations, publish the handful that look remarkable, and you have discovered nothing except that a long enough record cut into enough slices always yields a remarkable slice. Most of the machinery here exists to stop that — including stopping us from doing it.

Part 13 measures conditions one and two at a time. But you would never judge a chart from one planet alone — you read the whole configuration, and a trading day is no different: about 424 conditions are live on a single day, each carrying its own thirty-year record. The Dashboard puts that whole day in front of you so you can read it the way you actually work, and see whether the configuration predicts the move. That is Part 15, and it is the part worth your time.

Where do these numbers come from?

Every figure here was measured on the NIFTY 50 index (ticker ^NSEI), closing session, through 7 August 2026 — 7,605 trading days. When you see a number here, it is that dataset, not an illustration.

That is one market of 224: the app carries 200 individual stocks and 24 indexes, and the Explorer, the Scanner and the Backtest each begin with a market selector. NIFTY 50 is simply where these particular numbers were measured, not the limit of what can be measured — Part 16 is about the rest.

Part 01

One day, four numbers

Everything in the app is built from four measurements of a single trading day. Get these right and the rest is arithmetic.

A day of trading gives us four prices: the open, the high, the low and the close. We also keep yesterday’s close, high and low, because most of what matters is a comparison between today and yesterday.

The return

The headline number. How much did the market move, close to close?

return = (close − previous close) / previous close

Expressed as a percentage. A day that closes at 24,774.30 after closing at 24,383.60 the day before returned +1.60%. This is the definition used everywhere in the app — never open-to-close, which is a different question.

The gap

Did today open clear of yesterday’s entire range? Not merely above yesterday’s close — above yesterday’s high.

gap up   ⟺  open > previous high
gap down ⟺  open < previous low
otherwise, no gap

This is a stricter test than most people expect, and it is deliberate. An open above yesterday’s close happens roughly half the time and tells you little. An open above yesterday’s high means the market re-priced overnight past everything that traded the day before.

On our dataset, 16.73% of days gap up and 7.92% gap down. Those do not sum to 100% — the remaining 75% opened inside yesterday’s range. This matters later: gap up and gap down are two separate questions, not two halves of one.

The intraday move and the day’s range

intraday = (close − open) / open
range    = (high − low) / open

Intraday asks what happened during the session itself, ignoring the overnight jump. Range measures how violently the day swung, regardless of where it finished — a day can close flat having travelled 3% in both directions.

What these don't tell you.

A single day is a single observation. No statement in this app rests on one day. Everything below is about what happens when you collect many days that share some property of the sky.

Part 02

Bucketing days

A "bucket" is a set of trading days that share one thing about the sky. Every statistic in the app is computed over a bucket.

Take an axis — say Moon’s nakshatra. Every trading day in thirty years falls into exactly one of its 27 values. That gives 27 buckets, and each bucket is simply a list of dates. “Moon in Ashwini” might be 280 days scattered across the decades.

Four families of axis exist, and they differ in what a bucket is:

FamilyA bucket is…Example
Dailydays when a body sat in a sign, nakshatra or padaMoon in Chitra
KPdays when a Krishnamurti lord held a levelMoon's sub-lord is Venus
Panchangdays sharing an almanac valueShukla Ashtami
Planetary eventsthe trading days on which an event fellMoon–Jupiter conjunction

Two rules that shape every bucket

A day only counts if it has a previous close. The very first bar of the price history has nothing to compare against, so it forms no return, no gap, no outcome — and it is dropped. Every metric in a bucket therefore shares one denominator.

An event is mapped to a trading day. A conjunction that becomes exact on a Sunday did not happen on a trading day, so it is carried to the next session. This is why an event bucket’s day count can differ from its raw event count — and why the app says so explicitly rather than hiding the difference.

Only events are carried.

Daily, KP and Panchang read each trading day’s own sky, so a weekend or a holiday is dropped rather than folded into the next session.

Worked example · the landing page's demo dataset

raw Moon–Jupiter conjunctions found       545
  −  before NIFTY price history begins       78
  −  dated in the future                     59
  −  landing on the very first price bar       1
                                          ─────
  usable occurrences                       408

Every one of those subtractions is a real reason, and the app reconciles them in a test rather than quietly reporting 408 and hoping nobody asks where 545 went.

The session matters.

Panchang and KP values are read at a specific clock time, and the app measures two: the market open (09:15) and the close (15:30). These genuinely disagree — for tithi, the two snapshots differ on 26.5% of dates. There is no sunrise-based default, so the app makes you choose rather than picking one silently.

Part 03

Win rate, bias, and the number that disagrees with them

How often the market rose is a different question from how far it moved. A bucket can win more often than average and still lose money.

Win rate

win rate = up days / (up days + down days)

The denominator is decided days only. A day that closes exactly unchanged belongs to neither side, so it sits out of the tally rather than being quietly filed as a loss.

Across all 7,605 days, NIFTY’s unconditional win rate is 0.5327 — it closes up 53.27% of the time. That single number is the yardstick every single-axis bucket is measured against, and it is worth pausing on: the market goes up more often than it goes down. Any bucket that wins 53% of the time is unremarkable, not bullish.

Bias

bias = (up days − down days) / (up days + down days)

The same information on a different scale, running from −1 (every day down) to +1 (every day up), with 0 meaning evenly split. Algebraically it is just 2 × win rate − 1.

Average return — and why it can disagree

average return = (sum of all daily returns) / n

NIFTY’s unconditional average daily return is +0.0522%.

Win rate counts how often. Average return measures how far. They answer different questions and can point opposite ways: a bucket that rises on 60% of days by a tiny amount and falls on 40% of days heavily has a good win rate and a negative average return. Neither number is wrong; they are measuring different things. This is precisely why the app later lets you choose which one the significance test is run on.

Volatility

                  ______________________
volatility  =  √ Σ(return − mean)² / (n − 1)

The standard deviation of the bucket’s daily returns — how widely the day’s move scatters around its own average. NIFTY’s unconditional daily volatility is 1.4193%. The n − 1 rather than n is the standard small-sample correction; it matters when a bucket is small.

Volatility has no good side. A combination that reliably doubles volatility is genuinely notable and genuinely tradeable, but it is neither bullish nor bearish — which is why the app colours it by size rather than by direction.

Forward returns

forward 3-day return = close[day + 3] / close[day] − 1

Measured in trading days, not calendar days, and averaged only over days that actually have three sessions ahead of them. Days too near the end of the price history are skipped, never counted as zero. NIFTY’s unconditional 3-day forward return is +0.1591%.

This asks whether a condition leaves a mark that outlasts the session it appeared in. It also introduces a subtle problem that Part 10 has to fix.

Part 04

How sure are we? The Wilson interval

A win rate of 60% from 10 days and a win rate of 60% from 1,000 days are not the same claim. An interval says how much the number could move.

If you flip a fair coin ten times you will not get exactly five heads. Six is common, seven happens. So when a bucket of ten days shows seven up-days, “70%” is not the truth about that bucket — it is one noisy sample of it. A confidence interval is a range that says: given this sample, the underlying rate is plausibly somewhere in here.

The app uses the Wilson score interval at 95%. The obvious alternative — the “normal approximation” most textbooks teach first — breaks badly on small or lopsided samples, happily producing ranges that extend below 0% or above 100%. Wilson cannot: it is constructed so the interval always lies inside the possible range.

p = k / n            (the observed rate)
z = 1.96             (for 95% confidence)

              p + z²/2n            z          ⎧  p(1−p)     z²   ⎫
centre  =  ─────────────    half = ───── × √ ⎨ ─────── + ───── ⎬
             1 + z²/n             1 + z²/n    ⎩    n       4n²   ⎭

interval = centre ± half

k is the number of successes, n the number of trials. The z = 1.96 is the value that captures the middle 95% of a normal distribution — a constant you can look up, not something derived from your data.

Worked example · a bucket of 40 days, 24 of them up

p  = 24 / 40                         = 0.600
z² = 1.96²                           = 3.8416
z²/n = 3.8416 / 40                   = 0.0960
1 + z²/n                             = 1.0960

centre = (0.600 + 0.0480) / 1.0960   = 0.591
half   = (1.96 / 1.0960) × √(0.006 + 0.0006)
       = 1.788 × 0.0813               = 0.145

95% interval                          = 0.446 to 0.736

So a bucket showing a 60% win rate on 40 days is consistent with anything from 45% to 74%. Since the market’s own baseline is 53.3%, this bucket has told us almost nothing — the interval comfortably contains the baseline.

40%50%60%70%80%baseline 53.3%n = 40n = 400
The same 60% win rate, from two sample sizes. Ten times the days shrinks the interval by roughly √10 ≈ 3.2. Only the narrow one excludes the market’s baseline — and only that one is telling you something.

This is why the app shows n beside every rate, and why the drill-down reports the interval rather than the bare percentage. The width of the interval is the honesty of the number.

What it doesn't tell you.

A narrow interval means the rate is measured precisely. It does not mean the rate is different from the baseline, and it says nothing about whether the pattern will hold in the future. Those are Parts 6 and 11.

Part 05

Spans: why 300 days can be worth less than 30

Thirty days scattered across thirty years is thirty pieces of evidence. Thirty consecutive days is closer to one.

Suppose a bucket contains 300 trading days. That sounds like a lot. But if those 300 days are one unbroken stretch — say, the period Pluto spent in a single nakshatra — then you have not observed the condition 300 times. You have observed it once, for a long time, and whatever else was happening in the market during that year is baked into every one of those days.

So the app counts spans: the number of separate episodes.

a new span begins when
    the bucket value changes
  OR the previous matched day is not the immediately preceding trading day

The second condition is the one that is easy to omit and important to keep. If a filter or a date range has removed days from the middle of a run, the run is genuinely broken — even though the bucket value never changed.

Worked example · two real buckets, same app, very different evidence

Neptune in Pisces (Meena)
    days  955     spans   2     average run   477 days

Pluto in Purva Ashadha
    days 1662     spans   5     average run   332 days

Moon in a given nakshatra
    days ~280     spans ~280    average run   ~1 day

The Moon changes nakshatra roughly daily, so its buckets are hundreds of independent episodes spread across decades. The outer planets do not move: their “buckets” are multi-year eras of the calendar wearing a planetary label. Both have large n. Only one has meaningful evidence.

The app uses spans in three places. Buckets need at least 8 spans as well as 30 days before they are counted as testable. The sample-quality badge (thin / moderate / strong) reads spans alongside n. And the KP explorer prints a warning above any axis whose average run exceeds 30 days, calling those buckets eras, not recurring conditions.

Events are exempt.

A planetary event is a scattered occurrence, not a run of consecutive days, so “spans” has no meaning for it — event buckets are judged on n alone. This exemption is real, not an oversight, and it is why anything in the app that reads spans has to handle their absence.

Part 06

Is it more than chance? The Z-score

A single number that answers: how surprising is this, given how many days it rests on?

A bucket wins 58% of the time where the market wins 53%. Is that something? It depends entirely on how many days are behind it. Five percentage points on 30 days is noise. Five points on 3,000 days is not. We need one number that folds both together.

That number is the Z-score, and it works by asking: if this bucket were really no different from the baseline, how far from the baseline would a sample this size normally wander? That typical wandering distance is the standard error. Z is simply how many standard errors away we actually landed.

                observed − expected
Z  =  ───────────────────────
              standard error

                    _____________
standard error = √ p(1 − p) / n           (for a rate)

observed is the bucket’s own rate; expected is what we would see if the bucket were unremarkable — the market’s baseline; p is that expected rate and n the number of decided days.

Worked example · the same 5-point edge, on two sample sizes

expected p = 0.5327   (NIFTY's own baseline)
observed   = 0.58

n = 30      SE = √(0.5327 × 0.4673 / 30)   = 0.0911
            Z  = (0.58 − 0.5327) / 0.0911  = 0.52

n = 3000    SE = √(0.5327 × 0.4673 / 3000) = 0.0091
            Z  = (0.58 − 0.5327) / 0.0091  = 5.19

Identical edge, identical direction — and one is indistinguishable from noise while the other is enormous. This is the entire reason the app ranks and sorts on Z and never on the raw difference.

Reading a Z-score

|Z|Roughly how often chance alone produces it
1about 1 test in 3
2about 1 test in 20
3about 1 test in 370
4about 1 test in 15,800
5about 1 test in 1.7 million

Note the shape of that table. Z is not linear — the difference between 3 and 4 is a factor of forty. It is also signed: a Z of −3.2 is exactly as notable as +3.2, just in the other direction. The app sorts on the magnitude for that reason.

What it doesn't tell you.

A large Z says the pattern is unlikely to arise from chance in a single test. Nobody runs a single test. Part 8 is about what happens when you run 296,914 of them.

Part 07

Two conditions at once

When you combine Moon in Chitra with Venus in Kanya, the interesting question is not "how did that do" but "did combining them add anything".

Suppose Moon in Chitra wins 57% of the time, and Venus in Kanya wins 56%. What should the combination win? If the two conditions simply stack with no interaction, the combination should land somewhere near — but where exactly?

Not their product. 0.57 × 0.56 = 0.32, and a 32% expected win rate is obviously absurd. Multiplying is right for the probability of two independent events both happening; it is wrong for combining two rates that each already describe the same outcome.

The app uses a log-odds model instead. Odds are just a rate re-expressed: a 57% win rate is odds of 0.57/0.43 = 1.33 to 1. Taking logarithms turns “combining” into ordinary addition, which is exactly the behaviour we want.

logit(p) = ln( p / (1 − p) )

logit(expected) = logit(row) + logit(column) − logit(overall)

expected = 1 / (1 + e^−logit(expected))

Subtracting the overall rate once prevents double-counting the market’s own baseline tendency, which is already inside both marginal rates.

Worked example · Moon in Chitra × Venus in Kanya

row (Moon)      0.57    logit = ln(0.57/0.43) = +0.2819
column (Venus)  0.56    logit = ln(0.56/0.44) = +0.2412
overall         0.5327  logit = ln(0.5327/0.4673) = +0.1310

logit(expected) = 0.2819 + 0.2412 − 0.1310  = 0.3921
expected        = 1 / (1 + e^−0.3921)        = 0.5968

So if the combination adds nothing beyond its two parts, we should expect about 59.7% — noticeably higher than either part alone, which is correct and which the product model would never have given us. The residual is then how far the cell’s actual win rate sits from this 59.7%, and its Z is that residual divided by its standard error.

This is why the heatmap is coloured by residual and not by raw win rate. A grid coloured by win rate mostly shows you which rows and columns are individually strong — information you already have from the margins. Colouring by residual shows only what the combination contributes, and a cell that is merely “hot because one of its axes is hot” correctly reads as neutral.

Two different nulls, two different questions

A dashboard row therefore carries up to two Z-scores, and they answer different questions:

ColumnCompared againstAnswers
Zthe independence expectation (for a combination), or the market baseline (for a single condition)Does this add anything?
vs marketthe market baseline, alwaysIs this better than an average day?

A combination can beat the market handsomely and still contribute nothing — because both of its parts already did. The vs market column is shown only when it is not simply a repeat of Z.

Part 08

The problem with testing many things

Test enough combinations and something will look remarkable. This is the single most important idea on this page.

A |Z| of 3 happens by chance about once in 370 tests. That sounds reassuringly rare — until you notice the app tests 296,914 combinations for one market. At one in 370, pure chance should hand us roughly 800 cells at |Z| ≥ 3, every one of them meaningless.

Cricket makes the shape of the problem easy to see. Slice thirty years of scorecards finely enough — this batsman, at this ground, batting second, in April — and one of those slices will show a staggering average. It is staggering because it rests on a handful of innings, and you found it precisely because it was the most staggering of the thousands of slices you cut. Singling out the best-looking of our 296,914 combinations and calling it a discovery would be the same act: reporting the slice, not the cricketer. It is an easy mistake to make, and it is how a great many market patterns — planetary and otherwise — end up published.

The Bonferroni correction

The fix is to raise the bar in proportion to how many tests you ran. If you want a 5% chance of any false positive across the whole search, each individual test must clear a much higher threshold.

bar = the |Z| for which the chance of a single false positive
      is  α / (number of tests)        with α = 0.05

With 296,914 tests, that works out to |Z| ≥ 5.23. A cell must be more than five standard errors from its expectation before we are entitled to call it anything at all.

Worked example · what the bar does to a "great" result

a cell at |Z| = 4.33
    in a single test        → about 1 in 75,000 by chance   → striking
    among 296,914 tests     → about 4 such cells expected   → unremarkable

the bar for 296,914 tests                                   |Z| ≥ 5.23
the largest deviation actually found anywhere               |Z| = 4.33

The single most extreme result in the entire thirty-year search does not clear the bar set by the size of the search.

The second disclosure: found versus expected

The app also reports a looser comparison that is easier to check by eye. Of the 292,513 two-axis combinations large enough to measure, how many reach |Z| ≥ 2 — and how many should, by chance alone?

Worked example · the counting argument

cells large enough to test                     292,513
chance rate of |Z| ≥ 2                          ≈ 1 in 22
expected by chance alone                       ~13,309
actually found (direction)                      7,569

Fewer than chance predicts. Not more. If planetary combinations were adding signal, this number should exceed the expectation — it sits at little over half of it.

Why the app never uses the word "significant" on a row.

The sample-quality badge — thin, moderate, strong — describes how firm an estimate is: how many days, how many separate episodes, how narrow the interval. It is a statement about precision, never about significance. No row measured so far has cleared a significance test, and the badge is worded so that it could not be mistaken for saying otherwise on the day one does.

Part 09

Six factors: choosing what to measure

"Did the market go up" is one question about a day. It is not the only one worth asking.

Until recently every Z-score in the app measured exactly one thing: how often the market closed up. Volatility, gap frequency and the return columns were all displayed, but nothing tested them. A combination that reliably doubled volatility, or reliably gapped down while closing flat, was statistically invisible.

You can now choose which quantity the significance test runs on. The rows, the day counts and every descriptive column stay exactly the same — only the Z changes.

FactorAsksKindDirectional?
DirectionHow often does it close up?proportionyes
Gap upHow often does it open above yesterday's high?proportionno
Gap downHow often does it open below yesterday's low?proportionno
1-day returnHow far does it move on the day?meanyes
3-day returnHow far over the next three days?meanyes
VolatilityHow widely does the move scatter?dispersionno

Three kinds, three formulas

The kind is not a label — it determines both the test statistic and the way two conditions are combined.

proportion   Z = (p − E) / √( E(1−E) / n )
             combine by log-odds        (Part 7)

mean         Z = (m − E) / ( sd / √n )
             combine by addition:  row + column − overall

dispersion   Z = ( ln s − ln E ) / SE
             combine multiplicatively: row × column / overall

The mean form is the familiar t-style test. The dispersion form works on the logarithm because a standard deviation cannot go below zero and is strongly skewed — a symmetric test on s itself would be wrong.

The two gap factors are deliberately kept separate rather than combined into one. They are not mirror images: a day that gaps neither way counts against both denominators, so their rates do not sum to 1 (16.73% and 7.92% leaves 75% of days gapping neither way) and each carries its own information.

Directionality drives the colour. Direction and the two return factors are signed — up is bullish, and the heatmap uses the familiar green-red. The gap factors and volatility are not: a busier market is notable but it is not good, so those get a single amber magnitude scale instead. Colouring a high-volatility cell green would be a claim we do not mean to make.

Part 10

Three corrections that stop us fooling ourselves

Each of these was discovered by measuring, not by reasoning. Each one, left uncorrected, produced a result that cleared the significance bar — falsely.

The standard error formulas in Part 6 all rest on one assumption: that each observation is an independent piece of evidence. For “did the market close up”, on daily data, that is roughly true. For three of our six factors it is badly false, in three different ways.

Correction 1 · Overlapping windows

The 3-day forward return has a structural problem. Monday’s three-day window covers Tuesday, Wednesday and Thursday. Tuesday’s covers Wednesday, Thursday and Friday. They share two of their three days. Consecutive matched days are therefore measuring almost the same stretch of market — but the formula counts them as two independent observations.

correlation between two windows d days apart  =  max(0, 1 − d/h)

                    n²
effective n  =  ─────────────
                 Σᵢⱼ corr(i,j)

With a horizon h of 3 days: windows 1 day apart share ⅔, windows 2 days apart share ⅓, windows 3 or more days apart share nothing.

Worked example · the two extremes

60 days, all consecutive (one unbroken run)
    Σ corr ≈ 60 × 3        effective n ≈ 20   →  Z shrinks by √3 = 1.73×

60 days, all more than 3 trading days apart
    Σ corr  = 60           effective n  = 60   →  Z unchanged

Scattered days lose nothing. A long unbroken run counts for a third of its length — and long unbroken runs are exactly what the slow-moving outer planets produce.

Correction 2 · Clustering

Gaps are not spread evenly through history. They arrive in bursts when markets are turbulent and go quiet for months when they are calm. And the gap test is doubly exposed, because its threshold is yesterday’s range — so gap frequency is mechanically tied to how volatile the market currently is.

We can measure how badly this breaks the independence assumption directly. Chop the history into blocks of 20 trading days, count the gaps in each block, and compare how much those counts actually vary against how much a coin-flip model says they should.

                observed variance of block counts
inflation (VIF) = ───────────────────────────────────
                     n × p × (1 − p)     [the binomial prediction]

corrected n = n / VIF

Worked example · measured on NIFTY, 20-day blocks

factor        lag-1 correlation    VIF     effect on Z
direction          +0.075          1.19    negligible
gap down           +0.078          2.41    ÷ 1.55
gap up             +0.137          3.43    ÷ 1.85

before correction   gap up reached  |Z| = 6.22   (bar 5.23 — "a finding")
after correction    gap up reaches  |Z| = 3.36   (comfortably under)

Direction’s inflation of 1.19 is small enough to ignore, and is deliberately left uncorrected so that every previously published number in the app stays exactly as it was. That gap is recorded rather than quietly closed.

Correction 3 · Non-stationarity

The third problem cannot be fixed by adjusting a sample size, and understanding why is worth the paragraph.

Market volatility comes in regimes that last for years. Now recall Part 5: a bucket on a slow axis is a contiguous era. Neptune in Pisces is 955 trading days in two spans. Comparing that bucket’s volatility against a thirty-year average — which pools calm decades and crisis years together — does not measure Neptune. It measures whichever years Neptune happened to be passing through.

Worked example · why no correction factor rescues it

measured inflation for volatility, by block length:
    30 days    VIF  2.3
    60 days    VIF  4.1
   120 days    VIF  7.2
   250 days    VIF 13.4

A well-behaved quantity converges to a stable VIF.
This one grows without settling — the signature of a
process whose memory never really fades.

So there is no defensible number to divide by. The comparison itself is wrong, not merely under-corrected.

The app’s answer is to withdraw that specific reading rather than the whole factor. Volatility keeps its Z wherever the comparison is drawn from the same set of days — heatmap cells, scanner cells, and two-axis combinations, all of which compare a cell against margins built from exactly the days being measured, so the regime cancels out. Only the comparison against the thirty-year baseline is dropped, and those cells show “—”.

A fourth, smaller fix.

Volatility’s standard error depends on how fat-tailed the returns are (their kurtosis). Using each bucket’s own kurtosis seemed natural but is unstable: a four-day bucket’s kurtosis sits near its mathematical floor of 1, the standard error collapses toward zero, and Z explodes — four-day buckets were scoring |Z| ≈ 20. The app uses the market-wide figure instead, which on NIFTY is 12.54. For reference, a normal bell curve has a kurtosis of 3; index returns are far more extreme-prone than the textbook assumes.

Part 11

Out of sample: does it repeat?

The strongest test available: find the pattern in one stretch of history, then check it in a stretch you never looked at.

Every correction so far makes a single measurement more honest. None of them answers the question that actually matters to someone thinking about money: does it keep happening?

The scanner answers that by splitting history in two — the first 70% to search in, the last 30% held back. The split is strictly chronological, never random. A random split would scatter days from the same week into both halves, and since neighbouring days share market conditions, the held-back set would already contain most of the answer.

search here — 70%never looked at — 30%oldestmost recentsplit
A cell is marked consistent only if its deviation points the same way in the held-back period as it did in the search period.

One detail carries a lot of weight: the holdout’s expectation is rebuilt from the holdout period’s own row and column rates, never from the training period’s. Reusing the training rates would leak the very bias the check exists to detect, and the consistency flag would become decorative.

Excluding pairs that cannot be independent

Some axis pairs are guaranteed to agree, and testing them would be meaningless. Two layers of exclusion apply:

  • Structural — one axis is a direct lookup of the other. A planet’s sign determines its sign-lord completely, so pairing them tests nothing. Rahu and Ketu are always exactly 180° apart, which makes their signs a lookup — though notably not their nakshatras, since 180° divides evenly into 30° signs but not into 13°20′ nakshatras. Twenty-one pairs are excluded this way.
  • Measured — a symmetric uncertainty coefficient, computed on the actual days in your current selection, drops any pair that turns out near-redundant in practice.

Worth noting what is not excluded: a planet’s star-lord paired with its sub-lord — the single most-wanted KP combination — survives both gates, because a star lord genuinely admits nine different sub lords. It is a real pairing, not a lookup.

What the scanner is for.

It searches, and then it makes every candidate earn its place: take a pattern you noticed and ask whether it holds up in a stretch of history you never examined. That second step is what would turn a hit into something worth acting on rather than something worth admiring. On NIFTY 50, as the data stands today, 163,773 cells were tested; chance alone predicts about 442 at |Z| ≥ 3, and 108 actually reached it — fewer, not more, which is what a search that is not flattering itself looks like. The largest deviation found anywhere was 4.24, against a bar of 5.12, so nothing has survived the check yet. An empty screen is the ordinary outcome of a single run, not the answer to the question — and the scanner runs against any of the app’s 224 markets, of which exactly one has been searched this way.

Part 12

The backtest: from a pattern to a trade

A win rate is not a strategy. The backtest turns a set of dates into a set of simulated trades, with every fill rule stated.

Everything so far measured what the market did. The backtest asks a harder question: if you had acted on this, what would have happened? That requires deciding when you get in, when you get out, and at what price — and each of those decisions can flatter the result if made carelessly.

Getting in

Entry modeRule
FixedEnter long or short at the open or close, 0, 1 or 2 trading days after the event.
BreakoutWatch the event day’s high and low. Enter when one is broken — and the side that breaks decides the direction.

Breakout entry is the more honest of the two in one respect: you are not choosing a direction in advance, the market is telling you. It also means the direction setting is ignored in that mode, which the interface reflects rather than leaving as a trap.

Getting out

Four exits compete, and the first one hit wins: a stop loss, a trailing stop, a take profit, or simply running out of holding days. The simulation walks forward one bar at a time using the full high-low range, not just closes.

within a single bar, the conservative order is assumed:
    stop is checked BEFORE target

if the bar opens beyond the level (a gap through):
    the fill is the OPEN, not the level

Both rules deliberately favour the worse outcome. If a bar’s range spans both your stop and your target, we cannot know from daily data which came first, so we assume the loss.

Worked example · why a 1% stop can lose 7%

long entry at            100.00
stop placed at            99.00   (a 1% stop)

next day the market opens at 93.00 — the stop level
was never traded; the market gapped straight past it.

fill  = 93.00  (the open, not 99.00)
loss  = −7.0%  on a "1% stop"

This is not a bug and it is not avoidable on daily bars — an overnight gap cannot be traded through. The app flags exactly these exits with a (gap) tag so the oversized loss is explained rather than mistaken for broken arithmetic.

Scoring the trades

Returns are sign-adjusted: a short that profits from a falling market is recorded as a gain. Beyond the average and the win rate, two numbers matter:

max drawdown = the largest peak-to-trough fall
               of the running equity curve,
               with trades taken in date order

This measures the worst losing streak, not the worst single trade — the number that decides whether a strategy is survivable. It treats trades as sequential, which is a simplification: real holding periods can overlap.

Two panels, two different questions.

The results screen shows “market context” and “your strategy’s outcomes” separately, and they can disagree. The market-context panel is deliberately direction-unaware — it describes the raw market move around the event the same way whether you went long or short. So on a short trade it can show a rising market in green while your trade lost. That is intentional: one panel describes the market, the other describes your trade.

What the backtest does not include.

No brokerage, no taxes, no slippage beyond the gap rule, no bid-ask spread, no position sizing, no borrowing cost on shorts, and no limit on how many trades overlap. It is a measurement of a rule against history, not a projection of a trading account.

Part 13

What thirty years of NIFTY 50 actually show

All six factors, the full search, on one market, with every number stated exactly as measured.

Here is the complete result for NIFTY’s closing session across 7,605 trading days, measured through 7 August 2026. Each factor is tested independently, and each gets its own bar because each searches a slightly different population.

FactorCombinations testedBar to clearLargest foundCells at |Z|≥2Expected by chance
Direction296,9145.234.337,569~13,309
Gap up296,9145.233.9979~13,309
Gap down296,9145.234.06375~13,309
1-day return296,9145.234.758,459~13,309
3-day return296,9145.234.286,797~13,309
Volatility292,5135.234.624,953~13,309

Nothing has cleared the bar on any factor yet. The largest deviation found anywhere, across all six ways of measuring and nearly three hundred thousand combinations, is |Z| = 4.75 — against a bar of 5.23. And on every single factor, the number of combinations reaching the looser |Z| ≥ 2 threshold is below what chance alone predicts.

Volatility’s population is smaller (292,513) because, as Part 10 explained, it performs no test against the thirty-year baseline at all.

Every number in that table is NIFTY 50, closing session. The other 223 markets the app carries — 200 individual stocks and 23 further indexes, most with a decade or more of history — are each waiting for the same search, and it is the same three clicks to run. So this is a result about one index measured one way, not about the question.

Where this leaves the search

This is where the evidence stands today, and it is worth reading precisely rather than as a verdict:

  • It does not show that planetary positions have no relationship to prices. Absence of evidence at this sample size and this correction level is not evidence of absence.
  • It does narrow where an effect, if there is one, could still be hiding. A large, simple effect that held steady for thirty years — a nakshatra that reliably moved the Indian index by a tradeable amount — is exactly the kind of thing three hundred thousand tests are well positioned to catch, and these axes have not caught it on this index. What is left unsearched is where the search goes next: the 223 other markets in the app, finer conditions, effects that come and go with the era rather than holding for three decades — and, above all, the possibility that these conditions do something together that none of them does alone — which is Part 15, and the one you can go and check today. Part 14 sets the limits out one by one and Part 16 is the practical version; each of them is a direction rather than a dead end.
  • It leaves the base rates genuinely useful in the meantime. Knowing that a condition historically closed up 56% of the time, with a confidence interval wide enough to be honest about it, is real context for a chart you are already reading. It is not a signal, and the app never presents it as one.

There is something to take from the shape of the null, too. On every factor, fewer combinations reach |Z| ≥ 2 than chance alone would produce. A method with a thumb on the scale — a correction dropped here, a bar set conveniently there — shows the opposite symptom: a surplus of near-misses, not a shortfall. Whatever this method eventually finds will be worth believing for the same reason it has found nothing yet: the corrections in Part 10 are applied whether or not they are convenient, the bar is set by the size of the search rather than by the result, and the banner on the dashboard reads the live numbers instead of a hard-coded sentence — so it stops saying “nothing clears it” on the day something does.

Part 14

What these numbers cannot tell you

The limitations that a careful reader would find anyway, stated up front.

One market measured, many more not

Every figure here is NIFTY 50. A pattern absent from one index may well exist in another, and a pattern present in one market becomes far more convincing the moment it replicates in a second. The app holds 200 stocks and 24 indexes, so that argument is available to be made — it simply has not been made yet. It is one of the two biggest things left to go and find out — the other is Part 15’s — and Part 16 is about how to start on it.

Thirty years is fewer observations than it sounds

7,605 trading days is a lot of rows and not much independent evidence for anything slow. Saturn completes roughly one orbit. Any statement about a body that changes sign every few years rests on a handful of episodes, whatever the day count says — which is exactly what Part 5’s span counting exists to surface.

Two ayanamsas that must not be mixed

The KP screens use the Krishnamurti ayanamsa; the Daily and Panchang screens use True Chitrapaksha. Measured against each other, they sit 0.075°–0.087° apart in longitude and agree on the star-lord 99.44% of the time — but they are different frames, and a chart that mixed a condition from each would describe a sky that exists in neither system. The app therefore refuses to combine them rather than offering the option with a warning.

A deliberate omission

Karana is not offered as an axis. Eight of its eleven values are stored with a broken cycle in the underlying data, and the same defect appears in the event tables — an upstream generation bug, not a display issue. Rather than present a broken axis with a caveat, it is left out until the data is fixed.

Counts that legitimately disagree

A backtest’s occurrence count need not equal the day count of the bucket it came from. The backtest counts each event date once and drops events with no forward price data; the breakdown counts trading days and drops the first bar. Same underlying events, different tally, and the app says so on screen rather than letting you find the discrepancy yourself.

Survivorship and revision

Index history is not a neutral record. NIFTY’s constituents have changed many times; the index you can measure today is not the portfolio anyone held in 1996. This affects long-run return figures more than it affects direction or gap frequency, but it affects everything to some degree.

The one sentence to carry away.

Everything in this app is a historical base rate computed carefully and reported with its uncertainty. None of it is a prediction, nothing measured on NIFTY 50 has cleared a significance test yet, and the app is built so that if that changes — on this index or on any of the other 223 markets — the change will be visible in the numbers rather than in the marketing.

Part 15

Read the whole day

Part 13 measures one condition at a time, or a pair. A real trading day carries about 424 at once — and the Dashboard is where you read them together.

Look at the grain Part 13’s numbers are measured at. Each of those 296,914 tests asks about one thing: a single planetary event, a single Daily position, a single KP lord — or, in the two-axis rows, a screened pair of them. Precise, and deliberately narrow. It is the grain a machine can search exhaustively.

A day you would actually trade is not one condition. Open the Dashboard on any date and it lists every planetary condition live on it, each carrying its own thirty-year base rate — the whole configuration, in one screen, the way you would read a chart. Measured on NIFTY’s closing session across twenty sampled trading days, a single day carries about 424 measured combinations — roughly 360 KP, 44 Daily, 11 planetary events and 4 Panchang, though the exact mix changes from day to day.

What Part 13 hands youWhat a whole day lets you ask
Every condition's own thirty-year record, one at a timeDo ten of them landing together move a day more than any one of them does
A screened pair, against what the two would do independentlyDo today's conditions agree with each other, or cancel out
Each of six factors, measured separatelyDoes a day stacked with bullish-leaning conditions actually close up more often
Whether a pair repeats out of sampleWhich conditions carry the most weight when they land together

Which means Part 13’s headline is narrower than it first sounds. “Nothing has cleared the bar” describes conditions taken one and two at a time. Read at that grain, a day where a dozen conditions all lean the same way and a day where they pull against each other look identical. Read whole, they are obviously different days — and that difference is the thing you can go and put to the test.

And it is the easier question to answer

Here is the part that makes this genuinely promising rather than merely appealing. Part 8’s bar is high — |Z| ≥ 5.23 — for one reason: 296,914 tests were run, so the bar had to rise to match. Widening that search makes the problem worse, not better. Triples on the KP axes alone would multiply it by orders of magnitude and push the bar further out of reach.

A whole-day reading is the opposite kind of question. It is one hypothesis, not a search: does a day’s configuration, summarised into a single number, tell you anything about that day? One question faces a bar of roughly |Z| ≥ 2, not 5.23 — a threshold thirty years of data can comfortably reach. The atomic search is the hard way to find something. This is the tractable one, and it is sitting right there on the Dashboard.

What that summary should be is the genuinely interesting part, and it is wide open: a count of the conditions that agree, an average of their biases, a weighting by sample quality, by span count, or by family. Pick one, look at enough days, and you have a result nobody has.

One thing to be straight about.

We have not put a number on the whole-day reading, so nothing above is a claim that it works — and that is exactly what makes it worth doing. A result either way is a real result, and it would be reported here as plainly as Part 13’s was.

Go and check a day

You need no tooling you do not already have — the reading is the skill you brought with you. Open the Dashboard (it takes a free account), pick a date, and read the day whole rather than row by row. Which conditions are live together? Do they agree? Then scrub to the next day and the one after, and watch whether the days where everything lines up behaved differently from the days where it did not.

Then tell us what you found. These are the answers we most want: do some combinations carry more weight than others, and if so which — the rare ones, the ones with the most spans, the ones from a particular family? Does a day with many agreeing conditions behave differently from a day with few? Is there a handful that matters and a long tail that is noise? Say it with the dates you looked at, so it can be checked. The Community board is the place — a finding posted there is visible to everyone who comes after, which is what turns one person’s observation into something worth testing properly.

Part 16

Where to take this next

One day at a time is one direction. The other is sideways: the same machinery already points at 223 markets nobody has searched.

The Explorer, the Scanner and the Backtest all begin with a market selector, and it is not a short list. The app carries daily price history for 200 individual stocks and 24 indexes — NIFTY 50 and SENSEX, the Bank, IT, Auto, Pharma, FMCG, Metal, Energy, Realty, Media, PSU Bank, Infrastructure, MNC and Consumption sector indexes, and the Midcap and Smallcap families. 173 of those 224 carry ten years of history or more; the deepest runs to 8,986 trading days.

Part 13’s table covers exactly one of them. NIFTY 50 is the market the significance dashboard is currently pinned to, and it is where the corrections in Part 10 were measured — but the search it describes stops there. The other 223 searches are sitting behind a dropdown, unrun.

Things worth trying

  • Read a whole day, not a row. Part 15 leads this list because it is the one you could answer first. Every other item below refines a question the app already answers well. That one asks something new of a screen you already have, and it faces a far lower bar for the reason Part 15 sets out.
  • Take a NIFTY pattern and check it on a sector index. A combination that leans the same way in NIFTY Pharma and in NIFTY Metal — two indexes with almost nothing in common — is worth more than a larger deviation in NIFTY alone. Replication across unrelated markets is the strongest currency this field has, and no amount of further testing on a single index can buy it.
  • Look at single stocks, not only indexes. An index is dozens of companies averaged together, and averaging is precisely what dissolves an effect that lives in one sector or one kind of business. If a planetary condition means something for a metals company, an index where metals are a small slice will dilute it toward invisibility.
  • Read spans before you read day counts. Part 5 is the trap most searches fall into. A bucket of 300 days in 2 spans is one observation wearing a large number, and the fast bodies — Moon above all — are where a big n is genuinely made of hundreds of separate episodes.
  • Change the factor before you change the axis. Part 9’s six factors ask six genuinely different questions of the same days. A condition that does nothing to direction may do something to volatility or to the gap, and until recently nothing in the app tested those at all — which means they are the least picked-over ground here.
  • Try both sessions. The 09:15 and 15:30 snapshots disagree on the tithi for 26.5% of dates. That disagreement is not noise to be averaged away; it is an open question about which moment of the day the sky is supposed to be read for.
  • Carry it through to the backtest. A base rate is not a strategy. Part 12 exists so that a bucket you find interesting becomes an explicit rule — entry, stop, exit — and gets measured as a trade rather than admired as a percentage.

Tell us what is missing

This app expresses a particular family of questions: a position, a lord, an almanac value or an event, taken one or two at a time and measured against a trading day. That is not the whole of what practitioners actually use. The gaps are not hidden by design — they are mostly the things nobody has yet asked for in a form precise enough to build.

So the most useful thing you can send is a technique this app cannot currently express, stated the way you would state it to another practitioner: which bodies, which condition, read at which moment, and what you expect it to do to the price. A question phrased that precisely is most of the work of building it. Half-formed ones are welcome too — more than one thing now in the app began as somebody asking why a screen did not offer something obvious.

Two places to do that: the Community board, where the question and whatever comes of it stay visible to everyone, and Contact, which needs no account, if you would rather it came straight to us. Corrections to this page belong there too — if a formula here is wrong, or a caveat is missing, saying so is a contribution.

What this section is not.

None of the above is a roadmap or a promise about what gets built next. It is a list of doors already open in the app, and a genuine request to hear which ones are missing. The bar in Part 8 does not move for anything suggested here: a new axis gets measured exactly as harshly as everything already in the app, which is the only reason a result from it would be worth having.

Two screens carry all of this. The Explorer is where a market, an axis and a bucket become the numbers Parts 3 to 7 describe. The Dashboard is where a whole day arrives at once — and that is the one to open first, because the question it raises is the one nobody has answered yet. Pick a day, read what is active on it together, and tell us what you see.

Part —

Formula index

Every formula in one place, with the part that explains it.

QuantityFormulaPart
Return(close − prev close) / prev close01
Gap upopen > prev high01
Gap downopen < prev low01
Intraday(close − open) / open01
Day range(high − low) / open01
Win rateup / (up + down)03
Bias(up − down) / (up + down)03
Average returnΣ return / n03
Volatility√( Σ(r − mean)² / (n − 1) )03
Forward 3-dayclose[t+3] / close[t] − 103
Wilson centre(p + z²/2n) / (1 + z²/n)04
Wilson half-widthz/(1+z²/n) × √( p(1−p)/n + z²/4n² )04
Z (proportion)(p − E) / √( E(1−E)/n )06
Z (mean)(m − E) / ( sd / √n )09
Z (dispersion)(ln s − ln E) / √( (κ−1)/4n )09
Independence (proportion)logit⁻¹( logit(row) + logit(col) − logit(all) )07
Independence (mean)row + col − overall09
Independence (dispersion)row × col / overall09
Bonferroni bar|Z| for α / (tests), α = 0.0508
Effective n (overlap)n² / Σᵢⱼ max(0, 1 − d/h)10
Variance inflationobserved block variance / n·p·(1−p)10
Max drawdownlargest peak-to-trough of the equity curve12

Reference values · NIFTY 50 closing, 7,605 days through 2026-08-07

QuantityValue
Unconditional win rate0.5327
Average daily return+0.0522%
Daily volatility1.4193%
Average 3-day forward return+0.1591%
P(gap up)0.1673
P(gap down)0.0792
Kurtosis of daily returns12.54
Variance inflation — gap up3.43
Variance inflation — gap down2.41
Variance inflation — direction1.19
Bonferroni bar5.23

Every number on this page was measured on the live dataset rather than illustrated. Where a figure would change as new price data arrives, it is quoted with the date it was measured. The methods described here are implemented in the application itself and covered by its automated tests — including tests whose specific purpose is to fail if any factor ever does clear the significance bar, so that a real finding would be reported rather than missed.

Celestial Market Lens measures what markets did around historical planetary events. That is a description of the past. It is not a prediction, not a recommendation, and not investment, financial, legal or tax advice. Past results do not tell you what will happen next, and you are responsible for anything you do with money.

Where next?