This following code demo shows how an HFT-style regime switch can be built from a microstructure/state-transition network instead of traditional indicators.

It treats market behavior as a small Markov transition graph (4 states in the demo, e.g., strong/weak bull vs bear). Each directed edge is a transition probability Pij, converted into a “distance” using log(Pij): high-probability transitions become short distances, low-probability transitions become long distances. It then runs Floyd–Warshall to compute all-pairs shortest paths, capturing not only direct transitions but also the best multi-step routes between states.

From that shortest-path matrix it computes a Wiener-like index (sum of pairwise distances), which acts as a single scalar connectivity/compactness score for the market-state network. In HFT terms, this can be interpreted as a fast regime classifier:

Low Wiener-like index (“compact”) ? transitions concentrate in a tight subset of states (more predictable flow). An HFT strategy might allow higher quote aggressiveness, tighter inventory risk limits, or trend-biased execution because the state evolution is stable.

High Wiener-like index (“diffuse”) ? transitions spread out and paths between states are longer (more random/choppy flow). An HFT strategy might de-risk, widen spreads, reduce order size, increase cancellation thresholds, or prefer mean-reversion/market-making defense because predictability is lower and adverse selection risk is higher.

Although the demo uses hardcoded “directional” vs “choppy” transition matrices, in a real HFT system those probabilities would be estimated online from tick/level-2 features (imbalance, trade sign, short returns, volatility bursts). The result is a lightweight, mathematically interpretable graph metric that can drive latency-sensitive risk controls and parameter switching in an HFT engine.


Code
// TGr01.cpp - Zorro64 Strategy DLL (C++) - Markov Graph Wiener-like Index demo

#include <zorro.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define INF 1e30

struct Graph {
  int n;
  double* d;
};

static int Graph_pos(const Graph* g, int r, int c) { return r*g->n + c; }

static Graph* Graph_create(int n) {
  Graph* g = (Graph*)malloc(sizeof(Graph));
  if(!g) return 0;
  g->n = n;
  g->d = (double*)malloc(n*n*sizeof(double));
  if(!g->d) { free(g); return 0; }
  return g;
}

static void Graph_destroy(Graph* g) {
  if(!g) return;
  if(g->d) free(g->d);
  free(g);
}

static void Graph_reset(Graph* g) {
  for(int r=0; r<g->n; r++)
    for(int c=0; c<g->n; c++)
      g->d[Graph_pos(g,r,c)] = (r==c) ? 0.0 : INF;
}

static double probToDist(double p) {
  if(p <= 0.0) return INF;
  if(p > 1.0) p = 1.0;
  return -log(p);
}

static void Graph_linkProb(Graph* g, int i, int j, double p) {
  g->d[Graph_pos(g,i,j)] = probToDist(p);
}

static void Graph_allPairsShortest(Graph* g) {
  for(int k=0; k<g->n; k++)
    for(int i=0; i<g->n; i++)
      for(int j=0; j<g->n; j++) {
        int ij = Graph_pos(g,i,j);
        int ik = Graph_pos(g,i,k);
        int kj = Graph_pos(g,k,j);
        double cand = g->d[ik] + g->d[kj];
        if(cand < g->d[ij]) g->d[ij] = cand;
      }
}

static double Graph_wienerUndirectedLike(const Graph* g) {
  double W = 0.0;
  for(int i=0; i<g->n; i++)
    for(int j=i+1; j<g->n; j++) {
      double dij = g->d[Graph_pos(g,i,j)];
      double dji = g->d[Graph_pos(g,j,i)];
      W += 0.5*(dij + dji);
    }
  return W;
}

static void Graph_dump(const Graph* g, const char* title) {
  printf("\n%s", title);
  for(int r=0; r<g->n; r++) {
    printf("\n");
    for(int c=0; c<g->n; c++) {
      double v = g->d[Graph_pos(g,r,c)];
      if(v > 1e20) printf("  INF ");
      else printf("%5.2f ", v);
    }
  }
}

static void buildDirectional(Graph* g) {
  Graph_reset(g);
  Graph_linkProb(g,0,0,0.65); Graph_linkProb(g,0,1,0.30); Graph_linkProb(g,0,2,0.04); Graph_linkProb(g,0,3,0.01);
  Graph_linkProb(g,1,0,0.25); Graph_linkProb(g,1,1,0.60); Graph_linkProb(g,1,2,0.12); Graph_linkProb(g,1,3,0.03);
  Graph_linkProb(g,2,0,0.03); Graph_linkProb(g,2,1,0.12); Graph_linkProb(g,2,2,0.60); Graph_linkProb(g,2,3,0.25);
  Graph_linkProb(g,3,0,0.01); Graph_linkProb(g,3,1,0.04); Graph_linkProb(g,3,2,0.30); Graph_linkProb(g,3,3,0.65);
}

static void buildChoppy(Graph* g) {
  Graph_reset(g);
  Graph_linkProb(g,0,0,0.28); Graph_linkProb(g,0,1,0.24); Graph_linkProb(g,0,2,0.25); Graph_linkProb(g,0,3,0.23);
  Graph_linkProb(g,1,0,0.23); Graph_linkProb(g,1,1,0.27); Graph_linkProb(g,1,2,0.26); Graph_linkProb(g,1,3,0.24);
  Graph_linkProb(g,2,0,0.24); Graph_linkProb(g,2,1,0.26); Graph_linkProb(g,2,2,0.27); Graph_linkProb(g,2,3,0.23);
  Graph_linkProb(g,3,0,0.25); Graph_linkProb(g,3,1,0.23); Graph_linkProb(g,3,2,0.24); Graph_linkProb(g,3,3,0.28);
}

static void printRiskSwitch(double Wdir, double Wchop, double Wnow) {
  double thr = 0.5*(Wdir + Wchop);
  printf("\n\nRisk switch example:");
  printf("\nDirectional W = %.3f", Wdir);
  printf("\nChoppy      W = %.3f", Wchop);
  printf("\nThreshold   W = %.3f", thr);
  printf("\nCurrent     W = %.3f", Wnow);
  if(Wnow <= thr)
    printf("\nDecision: COMPACT regime -> higher risk / trend bias.");
  else
    printf("\nDecision: DIFFUSE regime -> reduce risk / mean-revert or flat.");
}

static int doMain()
{
  const int STATES = 4;

  Graph* Gdir = Graph_create(STATES);
  if(!Gdir) { printf("\nOOM creating directional graph"); return 1; }
  buildDirectional(Gdir);
  Graph_allPairsShortest(Gdir);
  double Wdir = Graph_wienerUndirectedLike(Gdir);

  Graph* Gch = Graph_create(STATES);
  if(!Gch) { printf("\nOOM creating choppy graph"); Graph_destroy(Gdir); return 1; }
  buildChoppy(Gch);
  Graph_allPairsShortest(Gch);
  double Wchop = Graph_wienerUndirectedLike(Gch);

  double Wnow = Wchop; // demo choice

  Graph_dump(Gdir, "\nDirectional graph shortest distances (-log p) after Floyd:");
  printf("\n\nWiener-like index (directional) = %.3f\n", Wdir);

  Graph_dump(Gch, "\nChoppy graph shortest distances (-log p) after Floyd:");
  printf("\n\nWiener-like index (choppy)      = %.3f\n", Wchop);

  printRiskSwitch(Wdir, Wchop, Wnow);

  Graph_destroy(Gdir);
  Graph_destroy(Gch);
  return 0;
}

// Zorro DLL entry point
DLLFUNC void run()
{
  if(is(INITRUN)) {
    doMain();
    quit("Done.");
  }
}

Last edited by TipmyPip; Yesterday at 18:27.