While Quant_IDQE Runs: TruthInTheFlip Farm Takes Shape

The current Quant_IDQE.tkr run is still maturing. At the time of writing, it is roughly halfway through the period I want to observe before drawing much from it.

That has created an interesting kind of development window.

Rather than continually disturbing the running experiment, I have been working on the machinery around TruthInTheFlip: how tracker data is selected, transformed, summarized, exported, inspected, and eventually plotted.

What began as a CSV utility has grown into something more general.

It is now TruthInTheFlip Farm.

From a CSV Utility to a Composable Farm

The first idea was simple: make it easier to extract useful CSV from a .tkr file.

That quickly exposed a more interesting structure.

There are really several different questions involved:

  • Where does the data come from?
  • Which part of the data do I want?
  • How should records be grouped?
  • What statistics should be calculated?
  • How should the result be presented?

Instead of combining those concerns into a growing collection of specialized commands, the Farm treats them as composable pieces.

A command can now read naturally from the outside inward.

For example:

csv tracker file "crypto3.tkr" total ZScore

means, conceptually:

file
    → tracker process
        → csv representation

Likewise, a segmented report can be expressed as:

csv segment file "crypto3.tkr" by_total 100B
    Index EndTotal MeanTrueZ EndTrueZ BestTrueZ

The pieces have distinct jobs.

file constructs a tracker source.

segment constructs a process over that source.

by_total 100B describes how segments are formed.

csv takes the resulting process and gives it an output representation.

This turned out to be a much better foundation than adding commands such as csv_segreport, csv_trackerreport, and every other combination that might eventually be useful.

The grammar composes instead of multiplying.

FluentCommandLine

A major part of this work became a reusable project of its own: FluentCommandLine.

It builds a typed command graph from ordinary functions.

Instead of parsing a traditional bag of strings and switches, each recognized function has typed arguments and a typed return value. The return value of one function can become the argument of another.

That means the command language itself reflects the software architecture.

A function returning a tracker source can be accepted wherever a tracker source is expected.

A function returning a FarmProcess can be consumed by csv.

A boundary can be passed to from or to.

The parser knows these relationships because they are real type relationships, not conventions encoded into command strings.

That also gives the system a useful self-describing property.

Help output can be generated from the same function registry the parser actually uses.

For that reason, the generated help is the bottom line for a particular build.

If static documentation ever falls out of sync with the executable, the executable’s generated help and metric listings are authoritative.

JWCFarm

The processing machinery also became general enough to deserve its own layer.

JWCFarm now contains reusable concepts such as:

  • FarmProcess
  • process lifecycle handling
  • process actions
  • metric catalogs
  • metric binding
  • metric projections

A Farm process does not need to know whether its output will become CSV, a future human-readable report, or something else.

It simply produces typed items through a lifecycle.

That separation became particularly useful once CSV was treated as a presentation adapter rather than something intrinsic to tracker or segment processing.

The same process can eventually support several representations without changing the process itself.

Selecting Ranges

The command language now supports typed boundaries as well.

For example:

from absTotal 200B

or:

from absWallclock 01:00:00

These can be composed with a source before processing.

A complete expression might look like:

csv tracker
    from absTotal 200B
    to absTotal 400B
    file "crypto3.tkr"
    absTotal AnticipatedPercentage ZScore

The distinction between navigation and measurement became important here.

A metric answers:

What is true at this record?

A boundary answers:

Where am I in the stream?

That is why absolute total, absolute wallclock, and UTC time make natural boundary coordinates, while many other perfectly valid metrics do not need to become part of the navigation language.

Windowing and Completeness

Windows introduced another subtle distinction.

A window can change the apparent local totals and statistics while the underlying tracker still has an absolute position in the full run.

That led to explicit absolute metrics such as:

absTotal
absWallclockTime
absWallclockTimeNs

It also raised the question of whether a produced record represents a complete unit.

Tracker records now default to complete, while windowing can mark completeness appropriately.

That lays the groundwork for a future whole process modifier that can discard incomplete output without contaminating the segmentation rules themselves.

The distinction matters.

A segment selector should decide how a segment is cut.

A process modifier should decide whether a produced result is accepted.

Keeping those ideas separate leaves the language room to grow without forcing the current release to grow with them.

Metrics Became a First-Class System

The metric system grew considerably during this work.

Tracker metrics now include not only the original counts and anticipation statistics, but also percentage forms, Z-scores, absolute coordinates, and Same/Different-derived statistics.

A particularly interesting addition came from examining the relationship between actual Same/Different transitions and the strategy’s Same/Different decisions.

The Tracker can now expose values such as:

same
diff
SamePercentage
DiffPercentage
ZScoreSame
ZScoreDiff

These are distinct from metrics such as ZScoreAnticipatedSame.

ZScoreSame asks how an unconditional always-guess-same baseline performed against chance.

ZScoreAnticipatedSame asks how the strategy performed specifically when it chose Same.

Those are related questions, but they are not the same question.

The Farm made that distinction easier to see because it made asking new questions cheap.

Nested Metrics

Segment output can also reach into the Tracker records it contains.

For example:

End.AnticipatedPercentage
End.SamePercentage
Z.ZScoreHeads

A segment does not need to duplicate every Tracker property as a top-level segment property.

Instead, the metric binder can follow a typed path.

This has become one of my favorite parts of the system.

A segment can expose meaningful structural anchors such as:

Begin
End
Z

and the caller can then select whichever Tracker metric is interesting at that anchor.

That keeps the segment model smaller while making the reporting surface richer.

Python Becomes a Consumer, Not a Requirement

Once the Farm can produce clean CSV on stdout, Python becomes a very natural downstream consumer.

A script can run the Farm, capture stdout, and load it directly into Pandas.

Conceptually:

result = subprocess.run(
    command,
    capture_output=True,
    text=True,
    check=True
)

df = pd.read_csv(io.StringIO(result.stdout))

From there the normal scientific Python ecosystem is available.

This has already been useful for plotting:

  • segment True-Z trajectories
  • anticipation percentage
  • Same/Different behavior
  • sign agreement
  • distributions
  • scatter plots
  • correlations

One useful lesson came from plotting percentage values near 50%.

Drawing a zero baseline made the interesting variation almost disappear because the data lived in a narrow band around 50.

The more meaningful view was either to draw a 50% reference line or subtract 50 and plot the edge directly.

That small plotting mistake actually helped clarify the semantics of the data.

This is the workflow I now expect to use repeatedly:

ask a question
    → select data with Farm
    → project metrics
    → visualize
    → quantify what looks interesting
    → promote broadly useful discoveries into metrics

In that sense, visualization is not merely the final presentation layer.

It can feed back into the metric model.

Testing the Whole Path

The Farm now has a focused automated test suite as well.

There are unit tests for areas such as:

  • Fluent environment context
  • module initialization
  • parsing
  • metric binding
  • nested metric paths
  • process lifecycle
  • abort behavior
  • CSV formatting
  • invariant numeric output

There are also integration tests that algorithmically create a real .tkr file, write several Tracker snapshots, and then run the Farm against it.

Those tests exercise the full path:

Fluent command
    → typed parsing
    → tracker boundary
    → source composition
    → real .tkr storage
    → FarmProcess
    → metric projection
    → CSV

Boundary tests verify inclusive from and to behavior over absolute totals, wallclock values, and UTC time.

At the moment, the test suite is green across the board.

That gives me much more confidence than simply knowing that a few commands work interactively.

Documentation

The Farm now has several layers of documentation:

The README provides the entry point.

The Farm guide explains the compositional language.

The Metrics guide explains what can be selected and how nested paths work.

The plotting guide shows how to take Farm output into Pandas and Matplotlib.

The executable remains self-describing, so documentation does not need to duplicate every generated metric listing forever.

Extensibility

Another architectural improvement came late in the work.

FluentCommandLine modules now have an initialization hook.

A module can register additional modules, parsers, contextual services, and other supporting infrastructure when it is installed into a FluentEnvironment.

This means advanced users can potentially extend an application without modifying the application’s own worktree.

That was an important requirement for me.

The host can provide a stable environment while modules contribute new command vocabulary and supporting behavior around it.

The mechanism is still deliberately small.

I would rather discover the next abstraction from actual need than turn the Farm into a general-purpose state machine before it has earned one.

What Comes Next

There are already obvious directions the Farm could grow.

One is a whole process modifier for accepting only complete process output.

Another is human-readable reporting.

The interesting thing is that neither appears to require breaking the current architecture.

CSV already established the pattern:

FarmProcess
    → representation

A future human-oriented command could simply provide another representation with a curated set of fields:

report tracker file "crypto3.tkr"

or:

report segment file "crypto3.tkr" by_total 100B

Unlike CSV, such a report would probably choose its fields for the user.

CSV is intentionally explicit and machine-friendly.

A human report should probably be opinionated.

That can come later.

For now, I want to keep the release boundary where it is.

Meanwhile, the Experiment Continues

All of this has been happening while Quant_IDQE.tkr continues to mature.

That is a satisfying relationship between the experiment and its tooling.

The experiment does not need to stop while I improve how I inspect it.

And the tooling does not need to know in advance exactly which questions will become interesting.

The Farm gives me a way to ask those questions compositionally as the data develops.

TruthInTheFlip began with a very simple proposition: sometimes it is useful to ask whether the next event will be the Same or Different rather than trying to predict the event directly.

The Farm reflects a similar philosophy at the software level.

Instead of trying to anticipate every future report, it provides a small set of pieces that can be composed into the report that is needed.

That feels like the right direction.

Truth in the Flip on GitHub

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.