Skip to content

[fix] gmx-sol - exclude points-farming volume from GMTrade - #8085

Open
mkzung wants to merge 9 commits into
DefiLlama:masterfrom
mkzung:fix/gmx-sol-points-farming
Open

[fix] gmx-sol - exclude points-farming volume from GMTrade#8085
mkzung wants to merge 9 commits into
DefiLlama:masterfrom
mkzung:fix/gmx-sol-points-farming

Conversation

@mkzung

@mkzung mkzung commented Jul 12, 2026

Copy link
Copy Markdown

Closes #7120.

GMTrade volume on GMX Solana includes wallets farming the GT points programme.
This excludes them.

How it works

Three numbers per wallet per day:

turnover volume / peak concurrent capital across all open positions
imbalance |long volume - short volume| / volume
positions distinct positions touched that day

Flagged when turnover >= 20 and either imbalance <= 0.15 or positions >= 8.

On 2026-05-20 that is 17 wallets holding $2.36B, the thirteen largest carrying 94%
of it: $3.9M to $11.0M of capital each, 29 to 41 positions, 20.0x to 32.8x
turnover. That is one operation rather than a population of traders.

The second branch exists because not every farmer hedges. On 2026-06-01 the
largest wallet on the venue ran 24.6x turnover on $28.6M across 76 positions at
imbalance 0.36, and a flat-book test alone let it through. The position count is
what keeps the wider test away from directional scalpers on one or two positions,
which is the other population that clears 20x turnover and which dominates the
early backfill.

Effect

trading day before after
2025-02-15 548.01 k 548.01 k
2025-03-15 368.67 M 368.67 M
2026-02-15 46.56 M 46.56 M
2026-05-20 3.22 B 2.89 B
2026-06-01 3.62 B 1.97 B
2026-06-04 3.30 B 2.99 B
2026-07-10 618.75 M 618.75 M
2026-07-17 1.53 B 1.53 B
2026-07-18 90.09 M 90.09 M

Sampling every 14th day from start to now instead of days I chose: 38 days, 2
change at all, none above 60% removed, every 2025 day identical.

Thresholds

Both are bounded on both sides rather than fitted.

Positions 8, 10, 15 and 20 give identical output on every day tested; 6 starts
reaching into 2025-03-15 (368.67 M to 348.97 M), so 8 sits just above the floor.

Turnover at 20 leaves quiet and historical days identical to the unfiltered
adapter. At 10 an ordinary day loses real volume (2026-07-17, 1.53 B to 1.37 B).
Above 30 the signal itself starts to go.

Limitation

A position that never trades during the day emits no event, and the subgraph has
no position entity, so its capital is invisible. Capital carried in is counted,
idle capital is not, which makes measured turnover an upper bound. Inflating peak
capital to stand in for idle positions, 2026-06-01 removes 55.4% at +0%, 52.7% at
+10%, 32.7% at +25%, 9.3% at +50%, and the 06-01 leader is only 23% clear of the
threshold at 24.6x. What limits this is that flagged wallets open a median 88% of
their positions fresh in-day and the leader trades 3,079 times across 76 of them.
Wallets near 20x have no such margin, which is the reason not to lower it.

Why not the alternatives

Fee rate does not work: totalFees is a bucket (price impact, borrowing,
liquidation, funding), as fees/gmx-sol.ts documents, so a threshold on it fits
noise.

Hold time does not work at the scale suggested in #7120. Implementing ">= 90% of
closes held under 60s" literally flags 4 wallets and 0.095% of the 2026-05-20 day,
because only 1.9% of that day's 37,003 closes were held under 60s. The variable is
pointing at something real, but the cut is orders of magnitude off.

This is not self-matched wash trading. GMX Solana is pool-based with no orderbook,
so a wallet cannot trade against itself. It is real trading against the pool that
exists to earn points, which is why the question of whether to exclude it is a
judgement call rather than an obvious bug.

Verification

Recomputing volume from tradeEvents reproduces the subgraph's own
volumeRecordDailies.tradeVolume exactly, so with nothing flagged the adapter
returns precisely the number it returns today.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

GMX Solana daily volume now comes from paginated tradeEvents, aggregated per wallet and position, with volume-farmer wallets excluded. The adapter also documents its volume methodology.

Changes

GMX Solana volume calculation

Layer / File(s) Summary
Trade aggregation models and farmer rules
dexs/gmx-sol.ts
Defines trade and wallet state, scaling and filtering thresholds, pagination settings, and volume-farmer classification.
Paginated trade processing
dexs/gmx-sol.ts
Fetches daily trade events in pages and aggregates exposure, position-size changes, trade counts, and long/short volume per wallet.
Daily volume output and methodology
dexs/gmx-sol.ts
Excludes classified farmer wallets from dailyVolume and adds the adapter’s volume methodology description.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Adapter
  participant GMXGraphQL
  participant WalletAggregation
  participant DailyVolume
  Adapter->>GMXGraphQL: Request paginated tradeEvents
  GMXGraphQL-->>Adapter: Return daily trade events
  Adapter->>WalletAggregation: Apply position and volume changes
  WalletAggregation-->>DailyVolume: Return non-farmer wallet volumes
  DailyVolume-->>Adapter: Return dailyVolume
Loading

Suggested labels: dexs, methodology, bug-fix

Suggested reviewers: treeoflife2

🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code matches the linked goal of filtering suspected wash-trading or farming volume from GMTrade using daily trade activity analysis.
Out of Scope Changes check ✅ Passed The changes stay focused on GMX Solana volume filtering, pagination safeguards, and adapter metadata with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Breakdown Methodology Check ✅ Passed PR only changes dexs/gmx-sol.ts, a volume adapter; it has no .add() labels and no fees breakdownMethodology requirement.
Income Statement Compliance ✅ Passed PASS: PR only changes dexs/gmx-sol.ts; fees/gmx-sol.ts already sets dailyFees to total fees and splits dailyRevenue/dailySupplySideRevenue so revenue = fees - supply side.
Version 2 Required ✅ Passed PASS: dexs/gmx-sol.ts is an existing adapter and still exports version: 1; the v2 requirement only applies to new adapters.
Pullhourly Required For Version 2 ✅ Passed dexs/gmx-sol.ts is still version: 1, so the v2 pullHourly requirement is not applicable.
Dune Adapters Are Version 1 ✅ Passed gmx-sol.ts uses a GraphQL subgraph via graphql-request, not any Dune helper, and already exports version: 1.
Income Statement Balance ✅ Passed The PR only changes dexs/gmx-sol.ts volume logic; it exports dailyVolume only and no dailyFees/dailyRevenue fields, so the fee balance rule isn't applicable.
Fetchoptions Usage ✅ Passed fetch(options) uses a single FetchOptions arg, returns only dailyVolume, and the adapter is version 1, so the v2 startOfDay rule doesn't apply.
Adapter Shape ✅ Passed Adapter stays simplest: one chain (chains: [CHAIN.SOLANA]) with a single start; no per-chain adapter/config map was introduced.
Efficiency And Error Handling ✅ Passed gmx-sol.ts uses GraphQL pagination only; no getLogs/api.call/try-catch swallowing/allowNegativeValue patterns, and constants have explanatory comments.
Methodology Keys ✅ Passed The new methodology object uses the display-name key Volume, not a code field like dailyVolume.
Title check ✅ Passed The title clearly describes excluding points-farming volume from GMX Solana and matches the change.
Description check ✅ Passed The description provides a detailed rationale, thresholds, effect, limitations, and verification, which is sufficient for a non-new-listing PR.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

The gmx-sol.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs gmx-sol.ts

🦙 Running GMX-SOL.TS adapter 🦙
---------------------------------------------------
Start Date:	Sat, 11 Jul 2026 00:00:00 GMT
End Date:	Sun, 12 Jul 2026 00:00:00 GMT
---------------------------------------------------

SOLANA 👇
Backfill start time: 12/2/2025
Daily volume: 97.01 M

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dexs/gmx-sol.ts`:
- Line 109: Update the error message in the events-length check to remove the
stray period after the exclamation mark, preserving the existing error condition
and behavior.
- Around line 101-109: Cap the pagination loop in the trade-event retrieval flow
around the events accumulator and request call by enforcing a maximum number of
pages and a timeout for each GraphQL request. Stop or fail clearly when either
limit is reached, while preserving the existing short-page termination and “Not
found daily data!” behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 33888a54-c3ba-488f-866a-fdf1ff2c3e4a

📥 Commits

Reviewing files that changed from the base of the PR and between 0dd1a21 and 1fc9494.

📒 Files selected for processing (1)
  • dexs/gmx-sol.ts

Comment thread dexs/gmx-sol.ts Outdated
Comment thread dexs/gmx-sol.ts Outdated
@mkzung

mkzung commented Jul 12, 2026

Copy link
Copy Markdown
Author

Both fair. Added a cap on the pagination loop so it cannot spin if the subgraph keeps handing back full pages, and reworded the error. The daily numbers are unchanged.

@github-actions

Copy link
Copy Markdown

The gmx-sol.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs gmx-sol.ts

🦙 Running GMX-SOL.TS adapter 🦙
---------------------------------------------------
Start Date:	Sat, 11 Jul 2026 00:00:00 GMT
End Date:	Sun, 12 Jul 2026 00:00:00 GMT
---------------------------------------------------

SOLANA 👇
Backfill start time: 12/2/2025
Daily volume: 97.01 M

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
dexs/gmx-sol.ts (1)

99-151: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Adapter should be version: 2 — the subgraph supports timestamp filtering.

The SQD subgraph accepts from/to timestamp parameters (line 105), confirming it supports granular time filtering. Per coding guidelines, subgraphs should use version: 2 with pullHourly explicitly set. The current version: 1 means the adapter runs once daily and uses options.startOfDay (a v1-only time anchor), which the guidelines say v2 adapters should not use.

Migrating to v2 would require:

  • Replacing options.startOfDay with options.startTimestamp/options.fromTimestamp
  • Adding pullHourly: true (or false with a comment if hourly pulling is impractical for farmer detection)
  • Adapting the farmer classification logic to work on hourly windows (a wallet with 20 trades/day may only have 1–2 trades/hour, falling below the trades >= 20 threshold)

If hourly farmer detection is genuinely impractical, version: 2 with pullHourly: false and an inline comment explaining why would still be more guideline-compliant than version: 1.

Based on learnings, version selection should be based on data source capabilities (timestamp filtering), not on query expense. Subgraphs explicitly fall into the v2 category. As per coding guidelines, "Use Version 2 when the source supports granular time filtering, such as on-chain logs, contract calls, subgraphs."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dexs/gmx-sol.ts` around lines 99 - 151, Update the adapter definition that
uses fetch to version 2 because the subgraph supports timestamp filtering.
Replace the v1 options.startOfDay anchor in fetch with the v2 start/from
timestamp field, and explicitly configure pullHourly; if disabling hourly pulls,
add the required rationale comment. Adjust isVolumeFarmer-based classification
as needed so farmer detection remains correct for the selected window size.

Sources: Coding guidelines, Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@dexs/gmx-sol.ts`:
- Around line 99-151: Update the adapter definition that uses fetch to version 2
because the subgraph supports timestamp filtering. Replace the v1
options.startOfDay anchor in fetch with the v2 start/from timestamp field, and
explicitly configure pullHourly; if disabling hourly pulls, add the required
rationale comment. Adjust isVolumeFarmer-based classification as needed so
farmer detection remains correct for the selected window size.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: af8d10ea-c548-4dc6-8176-0d3a8dbdeecb

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc9494 and 1f9e780.

📒 Files selected for processing (1)
  • dexs/gmx-sol.ts

@bheluga bheluga self-assigned this Jul 13, 2026

@bheluga bheluga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkzung thanks for the PR.
For the latest day run , I got 1.5B in volume both with and without filtering, which seems very high wrt OI (50M)
so this approach just solves the issue partially?

@mkzung

mkzung commented Jul 18, 2026

Copy link
Copy Markdown
Author

Fair. Ran it myself: 07-17 comes out 1531M with and without the filter, because nothing hits the thresholds that day.

The farmers just stopped. The filter is after the flat-book GT churn from #7120, and that was big in May/June and has died off:

date raw$M removed
2026-05-20 5249 39%
2026-06-01 4427 18%
2026-06-15 1071 <1%
2026-07-01 818 0%
2026-07-16 899 0%
2026-07-17 1531 0%

So it strips a lot on the days they're active (39% on 05-20), and there's nothing of that shape left now. The 1531M on 07-17 is ~4700 wallets, biggest ones at 3-18x turnover, none running a flat book at 20x+ the way the farmers do. The couple of flat-book wallets still around are at 12-14x and about 1% of the day, so dropping the threshold wouldn't move the number and starts catching normal traders.

The vol/OI thing is separate. This only pulls the farmers, it doesn't touch the ratio. If you want the ratio itself down that's a wider call on what counts as non-economic and needs its own rule. Either way works for me, can share the day by day if you want it.

mkzung added 7 commits July 20, 2026 01:27
…lpers

The flat-book test assumed a points farmer runs a hedged book. Not all do. On
2026-06-01 the largest wallet on the venue turned over 24.6x on $28.6M with
imbalance 0.36, so it passed: the filter caught 18.2% of that day and left 39.8%
behind.

Dropping the test outright is worse. It also protects a different population
that clears 20x turnover, directional scalpers working one or two positions with
small capital, and those dominate early history. On 2025-03-15 and 2026-02-15
turnover alone takes 60.7% and 71.7% of the day off wallets holding 1 to 7
positions on $39k to $755k of capital. Backfill runs to 2025-02-12, so that
would have rewritten real history.

So the rule is churn plus either a flat book or a wide one:
turnover >= 20 and (imbalance <= 0.15 or positions >= 8).

  day          before   after
  2025-03-15     8.0%    8.0%
  2026-02-15     0.0%    0.0%
  2026-05-20    38.7%   45.0%
  2026-06-01    18.2%   55.4%
  2026-06-04     3.8%   12.6%
  2026-07-10     0.0%    0.0%
  2026-07-17     0.0%    0.0%

Thresholds of 8, 10 and 15 positions give identical results, so the cut is
structural rather than fitted.
openSize.size is the number of distinct positions the wallet touched, because
closing sets the entry to 0 rather than removing the key. Reading it next to
'current size in usd' suggests it means positions still open, which is not what
the threshold is doing. Renamed to positionSize and said in the comment that
deleting closed keys would change the filter.
Two claims in the comment were measured before the position disjunct existed and
no longer hold.

Quiet days are not insensitive to turnover any more. At 10 the 2026-07-17 day
goes 1.53B to 1.37B, so 20 is load bearing on the low side as well as the high
side, and the note now says so.

The position threshold is flat from 8 to 20 rather than just 8, 10 and 15, and 6
is where it starts reaching the 2025 scalpers. That is the useful part: it gives
the floor.
Recomputed the comment's figures from the subgraph with a probe that does not
share code with the adapter. Two were wrong.

The protected wallets hold $3k to $755k, not $39k to $755k. The maxima were
right and the minimum was an order of magnitude out, which is what happens when a
number gets carried forward from an earlier subset instead of re-measured. Added
the 2026-02-15 leader as the concrete case, 221x turnover on $78k across one
position at imbalance 1.00.

The methodology string said wallets turning over 'more than 20x' are excluded.
The test is >= 20 and the smallest wallet in the 2026-05-20 set is at exactly
20.0x, so that sentence excluded a wallet the code includes.
The comment claimed flagged wallets carry no untouched positions into the day and
called it nil in practice. That cannot be checked: an untouched position produces
no trade event and the subgraph has no position entity, so its capital is
invisible either way. The claim had also been checked against the old rule's 15
wallets and was never rechecked after the rule started flagging 42.

It is false as stated. On 2026-06-01 the flagged wallets carry in a median 54.8%
of their peak capital and none end the day flat.

Measured capital is a lower bound, so turnover is an upper bound, and the result
is sensitive to it: inflating peak capital gives 55.4% removed at +0%, 52.7% at
+10%, 32.7% at +25%, 9.3% at +50%. The comment now carries those numbers plus
what limits the risk, which is that these wallets open 88% of their positions
fresh in-day and the leader trades 3079 times across 76 of them.
The pagination cap I added earlier exits the loop by running out of budget when
every page comes back full. There is no short page and no break, so the day is
only partly read and the adapter goes on to report that partial total as the
whole day.

Forcing it with MAX_EVENTS=100 on 2026-06-01 returns 2.64M for a day that is
1.97B, no error, no warning. A wrong number that looks like a plausible number is
worse than a crash.

A short page is the only evidence the day was fully read, so track it and throw
otherwise. The busiest day so far is 129k events against a cap of 1m, so this is
headroom rather than a live problem, but this venue went from single-digit
millions a day to billions inside a year.
MIN_TRADES never did anything. No single trade can move a position by more than
the wallet's peak exposure, since the position's own size is bounded by the peak
it contributed to, so volume <= trades * peak and turnover <= trades. Requiring
turnover >= 20 therefore already requires 20 trades. Measured it too: across six
days including every farming day the guard excludes zero wallets and moves the
result by 0.0000pp. Removing it takes the trades counter with it.

The comment was a 57 line block, the longest run in dexs/ by twenty lines, in a
directory where most adapters carry none. Much of it was per-day statistics that
belong in the PR and would be stale in a month. Kept the metric definitions, why
both branches of the test exist, and the idle-capital limit, which is the one
thing a future reader has to know before touching the thresholds.

Also folded the position-size update into a single map lookup instead of
has/get/set, which drops the 'as number' assertion.

No behaviour change: 06-01 1.97B, 05-20 2.89B, 07-17 1.53B, 2025-03-15 368.67M,
2026-02-15 46.56M, 07-10 618.75M, all identical before and after.
@github-actions

Copy link
Copy Markdown

The gmx-sol.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs gmx-sol.ts

🦙 Running GMX-SOL.TS adapter 🦙
---------------------------------------------------
Start Date:	Sat, 18 Jul 2026 00:00:00 GMT
End Date:	Sun, 19 Jul 2026 00:00:00 GMT
---------------------------------------------------

SOLANA 👇
Backfill start time: 12/2/2025
Daily volume: 90.09 M

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dexs/gmx-sol.ts`:
- Around line 102-105: Update the from timestamp construction in fetch to use
options.startTimestamp instead of options.startOfDay, while preserving the
existing conversion to milliseconds and ISO format. Keep the to timestamp based
on options.endTimestamp unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9a2c6223-3caa-4d75-b7e9-e2e9668f18cb

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9e780 and d5d319f.

📒 Files selected for processing (1)
  • dexs/gmx-sol.ts

Comment thread dexs/gmx-sol.ts
Comment on lines +102 to +105
const fetch = async (options: FetchOptions) => {
const from = new Date(options.startOfDay * 1000).toISOString();
const to = new Date(options.endTimestamp * 1000).toISOString();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use options.startTimestamp instead of options.startOfDay for time windows.

As per coding guidelines, use options.startTimestamp (or fromTimestamp) for event-based time windows rather than startOfDay. If this adapter runs hourly, startOfDay will incorrectly aggregate all events from midnight up to the end of the current hour, leading to grossly inflated day-to-date cumulative volume being reported for a single hour.

🛠 Proposed fix
 const fetch = async (options: FetchOptions) => {
-  const from = new Date(options.startOfDay * 1000).toISOString();
+  const from = new Date(options.startTimestamp * 1000).toISOString();
   const to = new Date(options.endTimestamp * 1000).toISOString();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fetch = async (options: FetchOptions) => {
const from = new Date(options.startOfDay * 1000).toISOString();
const to = new Date(options.endTimestamp * 1000).toISOString();
const fetch = async (options: FetchOptions) => {
const from = new Date(options.startTimestamp * 1000).toISOString();
const to = new Date(options.endTimestamp * 1000).toISOString();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dexs/gmx-sol.ts` around lines 102 - 105, Update the from timestamp
construction in fetch to use options.startTimestamp instead of
options.startOfDay, while preserving the existing conversion to milliseconds and
ISO format. Keep the to timestamp based on options.endTimestamp unchanged.

Source: Coding guidelines

@mkzung mkzung changed the title fix(gmx-sol): exclude points-farming volume from GMTrade [fix] gmx-sol - exclude points-farming volume from GMTrade Jul 19, 2026
@mkzung

mkzung commented Jul 19, 2026

Copy link
Copy Markdown
Author

Following up on my own numbers above - the 18% I gave for 06-01 was too low and
I've pushed a fix.

The filter wanted a flat book, on the assumption a farmer hedges. Not all do. The
biggest wallet on the venue that day was running 24.6x turnover on $28.6M across
76 positions at imbalance 0.36, and went straight through. It's now turnover >= 20
and either imbalance <= 0.15 or 8 or more positions.

That moves the two active days in my table: 05-20 goes from 39% to 45% removed and
06-01 from 18% to 55%. Quiet days and everything in 2025 are unchanged, and 07-17
still comes out 1531M either way.

My first attempt was to just drop the flat-book test, which was wrong - it also
keeps the filter off directional scalpers working one or two positions, and those
are most of the early backfill. Description now has the per-day table, what the
thresholds do either side of where they sit, and one limitation worth knowing: a
position that never trades doesn't show up in tradeEvents at all, so turnover is
an upper bound.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

filter wash trading volume from GMTrade

2 participants