mirror of
https://github.com/SHOGGOTH-SECTOR/sica-fondt.git
synced 2026-08-01 16:40:24 +00:00
M3d mev/main.f90: PGA all-pay auction simulation with bounded rationality, 0-1 knapsack block builder (dynamic programming), WENO5 shock-capturing PDE solver for adversarial dynamics. M3e tokenomics/main.f90: Euler-Maruyama SDE solver for token supply trajectories, stock-flow conservation (L2 invariant), kinked lending rate (L3: kink at U_opt, Aave-style), liquidation cascade detection, halving events as drift discontinuities. M3g microstructure/main.zig: Order book with spread/depth, non-linear slippage estimation (L2: function of order size), Almgren-Chriss optimal execution via Riccati (sinh/cosh trajectory), BoundedPrediction with invariant enforcement. Fix: M3b sociological sim_type was hardcoded as 'statistical' instead of 'sociological'.
223 lines
7.1 KiB
Prolog
223 lines
7.1 KiB
Prolog
#!/usr/bin/env swipl
|
|
%
|
|
% M3b -- Sociological & population dynamics sims
|
|
% Language: Prolog (game-theoretic equilibria as constraint satisfaction)
|
|
% Protocol: line-delimited JSON on stdin/stdout to hub.tcl
|
|
|
|
:- use_module(library(lists)).
|
|
:- use_module(library(apply)).
|
|
|
|
% -- Behavioral archetypes -----------------------------------------------
|
|
% Each archetype has a strategy and population share
|
|
|
|
archetype(herd_follower).
|
|
archetype(contrarian_whale).
|
|
archetype(mev_searcher).
|
|
archetype(passive_lp).
|
|
archetype(manipulator).
|
|
|
|
% -- Replicator dynamics --------------------------------------------------
|
|
% dx_i/dt = x_i * [f_i(x) - phi(x)]
|
|
% Discretized: x_i(t+1) = x_i(t) + dt * x_i(t) * [f_i(x) - phi(x)]
|
|
|
|
% Payoff matrix: row strategy vs column strategy
|
|
% Returns payoff for Row when playing against Col
|
|
payoff(herd_follower, herd_follower, 0.02).
|
|
payoff(herd_follower, contrarian_whale, -0.01).
|
|
payoff(herd_follower, mev_searcher, -0.03).
|
|
payoff(herd_follower, passive_lp, 0.01).
|
|
payoff(herd_follower, manipulator, -0.05).
|
|
payoff(contrarian_whale, herd_follower, 0.04).
|
|
payoff(contrarian_whale, contrarian_whale, -0.02).
|
|
payoff(contrarian_whale, mev_searcher, 0.01).
|
|
payoff(contrarian_whale, passive_lp, 0.02).
|
|
payoff(contrarian_whale, manipulator, -0.01).
|
|
payoff(mev_searcher, herd_follower, 0.06).
|
|
payoff(mev_searcher, contrarian_whale, 0.01).
|
|
payoff(mev_searcher, mev_searcher, -0.04).
|
|
payoff(mev_searcher, passive_lp, 0.05).
|
|
payoff(mev_searcher, manipulator, 0.02).
|
|
payoff(passive_lp, herd_follower, 0.03).
|
|
payoff(passive_lp, contrarian_whale, 0.01).
|
|
payoff(passive_lp, mev_searcher, -0.02).
|
|
payoff(passive_lp, passive_lp, 0.02).
|
|
payoff(passive_lp, manipulator, -0.04).
|
|
payoff(manipulator, herd_follower, 0.08).
|
|
payoff(manipulator, contrarian_whale, -0.03).
|
|
payoff(manipulator, mev_searcher, -0.02).
|
|
payoff(manipulator, passive_lp, 0.06).
|
|
payoff(manipulator, manipulator, -0.06).
|
|
|
|
% Fitness of strategy I given population state Pop = [(Archetype, Share), ...]
|
|
fitness(I, Pop, F) :-
|
|
findall(Pij, (
|
|
member((J, Xj), Pop),
|
|
payoff(I, J, Pij0),
|
|
Pij is Pij0 * Xj
|
|
), Payoffs),
|
|
sumlist(Payoffs, F).
|
|
|
|
% Average fitness across population
|
|
avg_fitness(Pop, Phi) :-
|
|
findall(XiFi, (
|
|
member((I, Xi), Pop),
|
|
fitness(I, Pop, Fi),
|
|
XiFi is Xi * Fi
|
|
), Products),
|
|
sumlist(Products, Phi).
|
|
|
|
% One replicator step: x_i(t+dt) = x_i + dt * x_i * (f_i - phi)
|
|
replicator_step(Pop, Dt, NewPop) :-
|
|
avg_fitness(Pop, Phi),
|
|
maplist(update_share(Phi, Dt, Pop), Pop, RawPop),
|
|
normalize_pop(RawPop, NewPop).
|
|
|
|
update_share(Phi, Dt, Pop, (I, Xi), (I, Xi1)) :-
|
|
fitness(I, Pop, Fi),
|
|
Xi1 is max(0, Xi + Dt * Xi * (Fi - Phi)).
|
|
|
|
normalize_pop(Pop, NormPop) :-
|
|
findall(X, member((_, X), Pop), Shares),
|
|
sumlist(Shares, Total),
|
|
(Total > 0 ->
|
|
maplist(norm_share(Total), Pop, NormPop)
|
|
;
|
|
NormPop = Pop
|
|
).
|
|
|
|
norm_share(Total, (I, X), (I, Xn)) :-
|
|
Xn is X / Total.
|
|
|
|
% Run N replicator steps
|
|
replicator_evolve(Pop, _, 0, Pop) :- !.
|
|
replicator_evolve(Pop, Dt, N, FinalPop) :-
|
|
N > 0,
|
|
replicator_step(Pop, Dt, Pop1),
|
|
N1 is N - 1,
|
|
replicator_evolve(Pop1, Dt, N1, FinalPop).
|
|
|
|
% -- Hegselmann-Krause bounded confidence ---------------------------------
|
|
% x_i(t+1) = mean({x_j : |x_j - x_i| < epsilon})
|
|
|
|
hk_step(Opinions, Epsilon, NewOpinions) :-
|
|
maplist(hk_update(Opinions, Epsilon), Opinions, NewOpinions).
|
|
|
|
hk_update(AllOpinions, Epsilon, Xi, NewXi) :-
|
|
include(within_confidence(Xi, Epsilon), AllOpinions, Neighbors),
|
|
length(Neighbors, Count),
|
|
sumlist(Neighbors, Sum),
|
|
NewXi is Sum / Count.
|
|
|
|
within_confidence(Xi, Epsilon, Xj) :-
|
|
abs(Xj - Xi) < Epsilon.
|
|
|
|
hk_evolve(Opinions, _, 0, Opinions) :- !.
|
|
hk_evolve(Opinions, Epsilon, N, Final) :-
|
|
N > 0,
|
|
hk_step(Opinions, Epsilon, Next),
|
|
N1 is N - 1,
|
|
hk_evolve(Next, Epsilon, N1, Final).
|
|
|
|
% -- Nash equilibrium search (constraint satisfaction) --------------------
|
|
% For 2-player symmetric games, find mixed strategy Nash equilibria
|
|
% via support enumeration
|
|
|
|
% Check if a mixed strategy (list of probabilities) is a Nash eq
|
|
% for a symmetric game with payoff matrix
|
|
is_nash_2p(Strategies, PayoffMatrix, Threshold) :-
|
|
length(Strategies, N),
|
|
length(PayoffMatrix, N),
|
|
expected_payoff_vec(Strategies, PayoffMatrix, ExpPayoffs),
|
|
max_list(ExpPayoffs, MaxPayoff),
|
|
forall((
|
|
nth0(I, Strategies, Si),
|
|
nth0(I, ExpPayoffs, Ei)
|
|
), (
|
|
Si =:= 0 ; abs(Ei - MaxPayoff) < Threshold
|
|
)).
|
|
|
|
expected_payoff_vec(Strat, Matrix, Payoffs) :-
|
|
maplist(expected_payoff_row(Strat), Matrix, Payoffs).
|
|
|
|
expected_payoff_row(Strat, Row, EP) :-
|
|
maplist(mul, Strat, Row, Products),
|
|
sumlist(Products, EP).
|
|
|
|
mul(A, B, C) :- C is A * B.
|
|
|
|
% -- BoundedPrediction output ---------------------------------------------
|
|
|
|
bounded_prediction(Value, Lower, Upper, Confidence, Horizon, Pred) :-
|
|
Lower =< Value,
|
|
Value =< Upper,
|
|
Confidence >= 0.0,
|
|
Confidence =< 10.0,
|
|
get_time(Now),
|
|
Timestamp is round(Now * 1000),
|
|
Pred = pred(Value, Lower, Upper, Confidence, Horizon, sociological, Timestamp).
|
|
|
|
format_prediction(pred(V, L, U, C, H, T, _)) :-
|
|
format(" value: ~4f [~4f, ~4f]~n", [V, L, U]),
|
|
format(" confidence: ~2f/10.00~n", [C]),
|
|
format(" horizon: ~w type: ~w~n", [H, T]).
|
|
|
|
% -- Self-test -------------------------------------------------------------
|
|
|
|
default_population([
|
|
(herd_follower, 0.30),
|
|
(contrarian_whale, 0.15),
|
|
(mev_searcher, 0.10),
|
|
(passive_lp, 0.35),
|
|
(manipulator, 0.10)
|
|
]).
|
|
|
|
run_self_test :-
|
|
prolog_flag(version, V),
|
|
format("M3b Sociological Sim -- SWI-Prolog ~w~n~n", [V]),
|
|
|
|
format("Replicator dynamics (100 steps, dt=0.1):~n", []),
|
|
default_population(Pop0),
|
|
format(" initial: ", []),
|
|
print_pop(Pop0),
|
|
replicator_evolve(Pop0, 0.1, 100, PopFinal),
|
|
format(" final: ", []),
|
|
print_pop(PopFinal),
|
|
nl,
|
|
|
|
format("Hegselmann-Krause (epsilon=0.2, 20 steps):~n", []),
|
|
HKInit = [0.1, 0.2, 0.25, 0.5, 0.55, 0.8, 0.85, 0.9],
|
|
format(" initial: ~w~n", [HKInit]),
|
|
hk_evolve(HKInit, 0.2, 20, HKFinal),
|
|
format(" final: ", []),
|
|
maplist(print_float, HKFinal), nl, nl,
|
|
|
|
format("BoundedPrediction check:~n", []),
|
|
(bounded_prediction(0.35, 0.20, 0.50, 7.80, '7d', Pred) ->
|
|
format_prediction(Pred)
|
|
;
|
|
format(" FAILED~n", [])
|
|
),
|
|
|
|
format("~nInvariant checks:~n", []),
|
|
(bounded_prediction(5.0, 6.0, 8.0, 7.0, '1h', _) ->
|
|
format(" L2 bounds: FAIL~n", [])
|
|
;
|
|
format(" L2 bounds: PASS (rejected lower > value)~n", [])
|
|
),
|
|
(bounded_prediction(5.0, 4.0, 8.0, 11.0, '1h', _) ->
|
|
format(" Confidence range: FAIL~n", [])
|
|
;
|
|
format(" Confidence range: PASS (rejected 11.0 > 10.0)~n", [])
|
|
),
|
|
|
|
format("~nAll models operational.~n", []).
|
|
|
|
print_pop([]) :- nl.
|
|
print_pop([(Name, Share)|Rest]) :-
|
|
format("~w:~3f ", [Name, Share]),
|
|
print_pop(Rest).
|
|
|
|
print_float(X) :- format("~3f ", [X]).
|
|
|
|
:- initialization((run_self_test, halt)).
|