Initialize AI Exchange closed-loop trading system repository.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 13:39:01 +08:00
commit 31ece2e99a
189 changed files with 27318 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
# Migration files live here.
+9
View File
@@ -0,0 +1,9 @@
create table if not exists venues (
id bigserial primary key,
code text not null unique,
name text not null,
timezone text not null,
status text not null default 'active',
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
+20
View File
@@ -0,0 +1,20 @@
create table if not exists instruments (
id bigserial primary key,
venue_id bigint not null references venues(id),
symbol text not null,
asset_class text not null,
base_asset text,
quote_asset text,
price_scale integer not null,
qty_scale integer not null,
tick_size numeric(20,10) not null,
lot_size numeric(20,10),
active boolean not null default true,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
unique (venue_id, symbol)
);
create index if not exists idx_instruments_venue_id on instruments(venue_id);
create index if not exists idx_instruments_active on instruments(active);
+16
View File
@@ -0,0 +1,16 @@
create table if not exists candles (
id bigserial not null,
instrument_id bigint not null references instruments(id),
timeframe text not null,
ts_open timestamptz not null,
ts_close timestamptz not null,
open numeric(20,10) not null,
high numeric(20,10) not null,
low numeric(20,10) not null,
close numeric(20,10) not null,
volume numeric(28,10),
source text not null default 'api',
created_at timestamptz not null default now(),
primary key (id, ts_open),
unique (instrument_id, timeframe, ts_open)
) partition by range (ts_open);
@@ -0,0 +1,13 @@
create table if not exists candles_2026_04
partition of candles
for values from ('2026-04-01 00:00:00+00') to ('2026-05-01 00:00:00+00');
create table if not exists candles_2026_05
partition of candles
for values from ('2026-05-01 00:00:00+00') to ('2026-06-01 00:00:00+00');
create index if not exists idx_candles_instrument_tf_open_desc
on candles (instrument_id, timeframe, ts_open desc);
create index if not exists idx_candles_instrument_tf_close_desc
on candles (instrument_id, timeframe, ts_close desc);
+23
View File
@@ -0,0 +1,23 @@
create table if not exists market_sessions (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
session_date date not null,
timezone text not null,
session_code text not null,
start_ts timestamptz not null,
end_ts timestamptz not null,
high numeric(20,10),
low numeric(20,10),
midpoint numeric(20,10),
status text not null default 'closed',
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
unique (instrument_id, session_date, session_code, timezone)
);
create index if not exists idx_market_sessions_instr_date
on market_sessions (instrument_id, session_date desc);
create index if not exists idx_market_sessions_instr_code_date
on market_sessions (instrument_id, session_code, session_date desc);
+23
View File
@@ -0,0 +1,23 @@
create table if not exists swings (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
kind text not null,
strength text not null,
price numeric(20,10) not null,
ts timestamptz not null,
left_bars integer not null,
right_bars integer not null,
confirmed boolean not null default true,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_swings_instr_tf_ts_desc
on swings (instrument_id, timeframe, ts desc);
create index if not exists idx_swings_instr_tf_kind_ts_desc
on swings (instrument_id, timeframe, kind, ts desc);
create index if not exists idx_swings_instr_tf_strength_ts_desc
on swings (instrument_id, timeframe, strength, ts desc);
+22
View File
@@ -0,0 +1,22 @@
create table if not exists dealing_ranges (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
high numeric(20,10) not null,
low numeric(20,10) not null,
equilibrium numeric(20,10) not null,
high_swing_id bigint references swings(id),
low_swing_id bigint references swings(id),
state text not null default 'valid',
ts_start timestamptz not null,
ts_end timestamptz,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create index if not exists idx_dealing_ranges_instr_tf_start_desc
on dealing_ranges (instrument_id, timeframe, ts_start desc);
create index if not exists idx_dealing_ranges_instr_tf_state_start_desc
on dealing_ranges (instrument_id, timeframe, state, ts_start desc);
+21
View File
@@ -0,0 +1,21 @@
create table if not exists liquidity_pools (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
side text not null,
pool_type text not null,
price_low numeric(20,10) not null,
price_high numeric(20,10) not null,
reference_ids jsonb not null default '[]'::jsonb,
status text not null default 'untouched',
created_ts timestamptz not null,
updated_ts timestamptz not null default now(),
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_liquidity_pools_instr_tf_status_created_desc
on liquidity_pools (instrument_id, timeframe, status, created_ts desc);
create index if not exists idx_liquidity_pools_instr_tf_side_created_desc
on liquidity_pools (instrument_id, timeframe, side, created_ts desc);
+5
View File
@@ -0,0 +1,5 @@
insert into venues (code, name, timezone)
values
('OKX', 'OKX', 'UTC'),
('LMAX', 'LMAX', 'UTC')
on conflict (code) do nothing;
+57
View File
@@ -0,0 +1,57 @@
insert into instruments (
venue_id,
symbol,
asset_class,
base_asset,
quote_asset,
price_scale,
qty_scale,
tick_size,
lot_size,
active,
meta
)
select
v.id,
'BTC-USDT',
'crypto',
'BTC',
'USDT',
2,
6,
0.01,
0.000001,
true,
jsonb_build_object('raw_inst_id', 'BTC-USDT-SWAP', 'product_type', 'swap')
from venues v
where v.code = 'OKX'
on conflict (venue_id, symbol) do nothing;
insert into instruments (
venue_id,
symbol,
asset_class,
base_asset,
quote_asset,
price_scale,
qty_scale,
tick_size,
lot_size,
active,
meta
)
select
v.id,
'ETH-USDT',
'crypto',
'ETH',
'USDT',
2,
6,
0.01,
0.000001,
true,
jsonb_build_object('raw_inst_id', 'ETH-USDT-SWAP', 'product_type', 'swap')
from venues v
where v.code = 'OKX'
on conflict (venue_id, symbol) do nothing;
@@ -0,0 +1,20 @@
create table if not exists displacement_events (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
direction text not null,
start_ts timestamptz not null,
end_ts timestamptz not null,
strength_score numeric(8,4),
body_ratio numeric(8,4),
has_fvg boolean not null default false,
is_valid boolean not null default true,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_displacement_events_instr_tf_end_desc
on displacement_events (instrument_id, timeframe, end_ts desc);
create index if not exists idx_displacement_events_instr_tf_dir_end_desc
on displacement_events (instrument_id, timeframe, direction, end_ts desc);
@@ -0,0 +1,21 @@
create table if not exists structure_events (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
event_type text not null,
direction text not null,
broken_level numeric(20,10) not null,
reference_swing_id bigint references swings(id),
displacement_event_id bigint references displacement_events(id),
accepted boolean,
signal_relevant boolean not null default true,
ts timestamptz not null,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_structure_events_instr_tf_ts_desc
on structure_events (instrument_id, timeframe, ts desc);
create index if not exists idx_structure_events_instr_tf_event_ts_desc
on structure_events (instrument_id, timeframe, event_type, ts desc);
+22
View File
@@ -0,0 +1,22 @@
create table if not exists fvg_zones (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
direction text not null,
upper numeric(20,10) not null,
lower numeric(20,10) not null,
start_ts timestamptz not null,
end_ts timestamptz not null,
fill_pct numeric(8,4) not null default 0,
status text not null default 'open',
related_displacement_id bigint references displacement_events(id),
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create index if not exists idx_fvg_zones_instr_tf_start_desc
on fvg_zones (instrument_id, timeframe, start_ts desc);
create index if not exists idx_fvg_zones_instr_tf_status_start_desc
on fvg_zones (instrument_id, timeframe, status, start_ts desc);
+23
View File
@@ -0,0 +1,23 @@
create table if not exists bias_snapshots (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
bias_tf text not null,
setup_tf text not null,
trigger_tf text not null,
snapshot_ts timestamptz not null,
daily_bias text not null,
confidence numeric(8,4),
execution_intensity text not null,
narrative_code text,
draw_side text,
range_id bigint references dealing_ranges(id),
reason_codes jsonb not null default '[]'::jsonb,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_bias_snapshots_instr_snapshot_desc
on bias_snapshots (instrument_id, snapshot_ts desc);
create index if not exists idx_bias_snapshots_instr_bias_snapshot_desc
on bias_snapshots (instrument_id, daily_bias, snapshot_ts desc);
+33
View File
@@ -0,0 +1,33 @@
create table if not exists trade_signals (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
model_code text not null,
side text not null,
status text not null,
bias_snapshot_id bigint references bias_snapshots(id),
entry_type text not null,
entry_low numeric(20,10),
entry_high numeric(20,10),
stop_loss numeric(20,10),
tp1 numeric(20,10),
tp2 numeric(20,10),
rr_tp1 numeric(8,4),
rr_tp2 numeric(8,4),
session_code text,
created_ts timestamptz not null,
expires_ts timestamptz,
invalidations jsonb not null default '[]'::jsonb,
evidence jsonb not null default '{}'::jsonb,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create index if not exists idx_trade_signals_instr_created_desc
on trade_signals (instrument_id, created_ts desc);
create index if not exists idx_trade_signals_instr_status_created_desc
on trade_signals (instrument_id, status, created_ts desc);
create index if not exists idx_trade_signals_instr_model_created_desc
on trade_signals (instrument_id, model_code, created_ts desc);
@@ -0,0 +1,29 @@
create table if not exists trade_executions (
id bigserial primary key,
signal_id bigint not null references trade_signals(id),
venue_order_id text,
execution_mode text not null,
side text not null,
entry_price numeric(20,10),
stop_loss numeric(20,10),
take_profit_1 numeric(20,10),
take_profit_2 numeric(20,10),
size numeric(28,10),
risk_pct numeric(8,4),
status text not null,
opened_ts timestamptz,
closed_ts timestamptz,
pnl numeric(28,10),
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create index if not exists idx_trade_executions_signal_id
on trade_executions (signal_id);
create index if not exists idx_trade_executions_status_created_desc
on trade_executions (status, created_at desc);
create index if not exists idx_trade_executions_mode_created_desc
on trade_executions (execution_mode, created_at desc);
+17
View File
@@ -0,0 +1,17 @@
create table if not exists backtest_runs (
id bigserial primary key,
model_code text not null,
instrument_id bigint references instruments(id),
timeframe_set jsonb not null default '{}'::jsonb,
started_ts timestamptz not null,
ended_ts timestamptz,
config jsonb not null default '{}'::jsonb,
summary jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_backtest_runs_model_started_desc
on backtest_runs (model_code, started_ts desc);
create index if not exists idx_backtest_runs_instr_started_desc
on backtest_runs (instrument_id, started_ts desc);
@@ -0,0 +1,20 @@
create table if not exists backtest_results (
id bigserial primary key,
backtest_run_id bigint not null references backtest_runs(id),
signal_id bigint references trade_signals(id),
outcome text not null,
mfe numeric(20,10),
mae numeric(20,10),
tp1_hit boolean,
tp2_hit boolean,
invalidated_before_entry boolean,
error_tags jsonb not null default '[]'::jsonb,
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index if not exists idx_backtest_results_run_id
on backtest_results (backtest_run_id);
create index if not exists idx_backtest_results_outcome
on backtest_results (outcome);
+22
View File
@@ -0,0 +1,22 @@
create table if not exists sweep_events (
id bigserial primary key,
instrument_id bigint not null references instruments(id),
timeframe text not null,
side_swept text not null,
pool_id bigint not null references liquidity_pools(id),
sweep_high numeric(20,10) not null,
sweep_low numeric(20,10) not null,
sweep_ts timestamptz not null,
close_back_inside boolean not null default false,
validation_level text not null default 'weak',
status text not null default 'active',
meta jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
unique (instrument_id, timeframe, pool_id, sweep_ts)
);
create index if not exists idx_sweep_events_instr_tf_ts_desc
on sweep_events (instrument_id, timeframe, sweep_ts desc);
create index if not exists idx_sweep_events_pool_ts_desc
on sweep_events (pool_id, sweep_ts desc);