Skip to content

AtalayEge/SpinMarket

Repository files navigation

SpinMarket

A voter-model-inspired complex network opinion dynamics short-term volatility predictor. At its core, it generates a random complex network with arbitrary connectivity and predefined parameters, then implements three different probabilistic Monte Carlo step-state changes to each node's opinion value (corresponding to buy/long or short/sell positions) and generates a random walk trajectory for the current price of the simulated market.

Model Description

The primary mechanism driving opinion change is the voter model, where each node's spin value $S_i \in {-1, +1}$ samples its $k$ nearest neighbors and flips with probability:

$$p_i = \frac{1}{2N_k} \sum_{j}^{k} \left(1 - S_i S_j\right)$$

where $N_k$ is the total number of neighbors of node $i$, $S_i$ is the selected node's spin, and $S_j$ are the neighboring spin values. This probability tends to $1$ as all neighbors hold the opposite spin from $S_i$, and tends to $0$ when all neighbors agree.

The secondary mechanism is defined by the momentum traders. Instead of interacting with their neighbors, these nodes change their opinion by observing the price history. They do so by tracking market indicators such as moving averages and the RSI. Each momentum node is assigned a randomly sampled time frame and a randomly selected indicator, and probabilistically updates its opinion during the simulation based on those signals. Their role is to drive the price in a more reactionary, trend-following manner and inject directional bias into the dynamics.

The third and final mechanism is random flipping: these nodes simply flip a coin each step and update their opinion accordingly. They serve as a noise floor and, crucially, prevent the voter model nodes from ever reaching full consensus, since voter nodes will always have some fraction of neighbors whose spins are changing randomly.

Price Transition

At each time step, a fraction $p$ of nodes is sampled and their spins are updated according to their respective mechanisms. The net opinion signal is the wealth-weighted sum of all spin changes in that step:

$$\Sigma = \sum_{i \in \text{flipped}} \Delta S_i \cdot w_i$$

where $w_i \in {1, 10, 100, 1000}$ is the wealth-tier impact weight of node $i$ and $\Delta S_i = \pm 1$ depending on the direction of the flip.

A dynamic set of $N_s$ candidate price levels is then constructed as a uniform grid centered on the current price $P_t$:

$$\mathcal{P} = \left\lbrace P_t \left(1 - \rho\right),\ \ldots,\ P_t \left(1 + \rho\right) \right\rbrace$$

where $\rho$ is the price range parameter. The next price $P_{t+1}$ is then drawn as follows:

  • If $\Sigma = 0$: the price does not move, $P_{t+1} = P_t$.
  • If $\Sigma \neq 0$: only the $N$ candidate prices strictly above (if $\Sigma > 0$) or below (if $\Sigma < 0$) $P_t$ are considered. Each candidate is ranked by distance from $P_t$, with $j = 1$ being the nearest and $j = N$ the farthest. A transition rate is assigned to each candidate:

$$r_j = j^{-\alpha} \ln\left(|\Sigma| \cdot j\right)$$

The power-law factor $j^{-\alpha}$ suppresses large jumps, while the logarithmic term $\ln(|\Sigma| \cdot j)$ scales the rates with the magnitude of the net opinion signal. The next price is then sampled from this distribution:

$$P\left(P_{t+1} = p_j\right) = \frac{r_j}{\lambda}, \qquad \lambda = \sum_{k=1}^{N} r_k$$

Parameters and Calibration

What makes this approach potentially more practical than some machine learning predictors is the abundance of interpretable, tunable parameters. While their existence makes the fitting problem harder, it also allows the model to be adapted to different markets and different regimes without retraining from scratch. For example, when market volatility increases, it can be sufficient to decrease $\alpha$ and $\rho$ rather than rebuilding the model entirely. If richer data about a given market is available, the graph-defining parameters such as the connectivity $k$ and the wealth-tier populations $R_1, \ldots, R_4$ can be set more realistically.

Optimization can be approached in multiple ways: visually, by overlaying simulated trajectories on historical price data and tuning by inspection, or more formally, by minimizing any statistical or functional measure of distance between the simulated and observed distributions. While the formal approach seems best on paper, in practice penalizing outlier trajectories for failing to match the real price path tends to produce overly conservative parameters that leave insufficient room for sharp price moves, and the resulting output statistics end up carrying no predictive power.

Intended Use

This model is intended as a short-term volatility predictor that fits into a market regime, not as a price predictor or a signal generator. It can inform an understanding of how collective opinion dynamics drive volatility under different conditions, but how that translates into a trading strategy depends entirely on the implementation context. Using it as a clean directional signal or price forecast is strongly discouraged.

Repository

SpinMarket.py is the main descriptive module and serves as the engine behind the Monte Carlo simulations. MarketIndicators.py defines the small set of market indicators used by momentum trading nodes, while MIDecisions.py contains the decision logic that translates those indicators into buy, sell, or hold signals.

Example.py ties everything together: it calls the required functions, generates simulated trajectories, and visualizes them. An example output from this script is shown below.

Example trajectories

This example is constructed from SOLUSDT data taken from Binance at a 15-minute resolution using the closed price. With 1000 historical data points and 200 Monte Carlo steps, the total historical time frame is 250 hours and the simulated window is 50 hours (roughly 2 days). All of these can be adjusted depending on the market, data source, and desired duration. This model is best suited for capturing short-term volatility, as it is by nature simulating a reactionary market, though longer time frames are worth exploring.

Files

File Description
SpinMarket.py Core simulation: graph generation, spin dynamics, price transitions
MarketIndicators.py Technical indicators: exponential moving averages (quarter, half, full length) and RSI
MIDecisions.py Decision logic mapping indicator signals to BUY / SELL / HOLD
Example.py Example script: generates and visualizes simulated trajectories
Toy Data/ Sample .npy price histories (BTC, ETH, SOL - 250H history)

Setup

python -m venv venv
source venv/bin/activate  # on Windows: venv\Scripts\activate
pip install -r requirements.txt

Usage

python Example.py

Requirements

  • Python 3.9+
  • numpy, pandas, networkx, matplotlib

Future Work

  • The graph connectivity parameters $k$ and the wealth-tier population sizes $R_1, \ldots, R_4$ are currently set arbitrarily. They do produce reasonable dynamics, but grounding them in empirical market data would improve the model significantly.
  • The set of market indicators available to momentum traders is minimal. Expanding it with a richer indicator library would give momentum nodes more expressive and realistic decision-making.
  • Backtesting coverage is limited and there is no established strategy for it. A clear, reproducible backtesting framework would substantially increase confidence in the model's outputs.

Author

Atalay Ege

License

This project is licensed under the MIT License.

About

A voter-model-inspired complex network simulator of short-term market opinion dynamics.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages