An in-process Webull, for a consumer's tier-1 tests and for the conformance suite.
It is not a mock. Nothing is stubbed, no expectation is recorded, no call is
verified. It is a real implementation of DpExchange.Core.Venue answering from memory,
and it runs the same conformance suite as the real adapter.
Two rules
Less capable is allowed. Differently capable is not. Where this cannot answer it returns an error, never an empty success.
It never rewrites a value the caller supplied, and never stamps the current clock —
@at is fixed, because a fake that stamps utc_now/0 cannot be used to test anything
about freshness and is itself the substitution this family refuses.
It models the three things that make this venue different
- Credentials are required for market data.
get_price/2without them is{:refused, :missing_credentials}, because the real venue signs every call and has no anonymous endpoint. A fake that answered anyway would let a consumer's test pass while the real call returns 401. - No volume.
volumeisnilon every quote and every bar, matching a venue that reports none. Returning0would look like a real measurement of no trading. - UAT has no stream.
subscribe/2underenvironment: :uatrefuses, exactly as the real feed does, rather than delivering fake production data.