Development Reference
Project Structureβ
QUANTAF/
βββ src/main/java/io/github/vinipx/quantaf/
β βββ config/ # Configuration & environment
β β βββ QuantafConfig.java # Singleton YAML config loader
β β βββ EnvironmentResolver.java # LOCAL/CI/STAGING detection
β βββ core/ # Business logic layer
β β βββ MarketMaker.java # Statistical data generation
β β βββ TradeLedger.java # Cross-source reconciliation
β β βββ TradeLedgerAssert.java # Assertion DSL for reconciliation
β β βββ BusinessCalendar.java # NYSE/LSE/TSE business day logic
β β βββ model/ # Domain models
β β βββ OrderConfiguration.java # Order config with Side/OrderType/TIF enums
β β βββ TradeRecord.java # Normalized trade record (FIX/MQ/API)
β β βββ ReconciliationResult.java# Field-level comparison results
β βββ protocol/ # Protocol adapters layer
β β βββ fix/ # FIX protocol (QuickFIX/J)
β β β βββ FixSessionManager.java # Multi-version session lifecycle
β β β βββ FixInitiatorWrapper.java # Client-side (sends orders)
β β β βββ FixAcceptorWrapper.java # Server-side (exchange stub)
β β β βββ FixInterceptor.java # Evaluates stubs, sends responses
β β β βββ FixStubRegistry.java # WireMock-like predicateβresponse registry
β β β βββ FixMessageBuilder.java # Fluent builder for FIX messages
β β β βββ FixVersion.java # FIX42/FIX44/FIX50 enum
β β βββ mq/ # Message queue adapters
β β β βββ MessageBroker.java # Pluggable interface
β β β βββ ActiveMqBroker.java # ActiveMQ Artemis (Jakarta JMS)
β β β βββ IbmMqBroker.java # IBM MQ skeleton
β β βββ rest/ # REST API adapter
β β βββ RestClientWrapper.java # RestAssured wrapper with OAuth2
β β βββ OAuth2TokenManager.java # Token lifecycle management
β β βββ PortfolioApiClient.java # Typed portfolio REST client
β βββ ai/ # AI Cortex layer
β β βββ LlmProvider.java # Pluggable LLM interface
β β βββ FixScenarioAgent.java # NLP β OrderConfiguration
β β βββ SmartStub.java # Intent β ISO 20022 XML
β β βββ providers/
β β βββ OpenAiProvider.java # OpenAI via LangChain4j
β β βββ OllamaProvider.java # Local Ollama via LangChain4j
β βββ reporting/ # Allure integration
β βββ AllureFixAttachment.java # FIX message formatting & attachment
β βββ ReconciliationReportStep.java# Reconciliation as Allure steps
βββ src/main/resources/
β βββ quantaf.yml # Framework configuration
β βββ quickfix-FIX42.cfg # QuickFIX/J config for FIX 4.2
β βββ quickfix-FIX44.cfg # QuickFIX/J config for FIX 4.4
β βββ quickfix-FIX50.cfg # QuickFIX/J config for FIX 5.0
β βββ logback.xml # Logging configuration
βββ src/test/java/io/github/vinipx/quantaf/
β βββ unit/ # Unit tests
β β βββ MarketMakerTest.java # Statistical validation
β β βββ FixStubRegistryTest.java # Stub matching & message builder
β β βββ TradeLedgerAssertTest.java # Reconciliation & assertions
β βββ scenarios/ # TestNG scenario tests
β β βββ QuantafBaseTest.java # Abstract base (BeforeSuite/AfterSuite)
β β βββ HighFrequencyOrderTest.java # Full workflow tests
β βββ bdd/ # Cucumber BDD
β βββ runners/
β β βββ CucumberTestRunner.java # TestNG-Cucumber bridge
β βββ steps/
β βββ OrderStepDefs.java # Step definitions
βββ src/test/resources/
β βββ features/
β β βββ order_lifecycle.feature # BDD feature file (4 scenarios)
β βββ testng.xml # TestNG suite configuration
βββ build.gradle.kts # Gradle build (Kotlin DSL)
βββ settings.gradle.kts # Project name: QUANTAF
βββ gradle.properties # JVM args, parallel, caching
βββ docker-compose.yml # ActiveMQ Artemis local service
βββ documentation/ # Documentation site (Docusaurus)
β βββ docs/ # Documentation source (Markdown)
β βββ src/ # React components & custom CSS
β βββ static/ # Static assets (logo, images)
β βββ docusaurus.config.js # Site configuration
β βββ sidebars.js # Navigation sidebar
β βββ package.json # Node.js dependencies
βββ docs.sh # Documentation server launcher (zsh)
βββ .github/workflows/
β βββ ci.yml # Build & test pipeline
β βββ docs.yml # Docs deployment to GitHub Pages
βββ README.md
Key Classes & Interfacesβ
MessageBroker (Layer 1 β Protocol Adapters)β
The pluggable interface for message broker interactions:
public interface MessageBroker {
void publish(String destination, String payload);
CompletableFuture<String> listen(String destination, Duration timeout);
CompletableFuture<String> listenWithFilter(
String destination, Predicate<String> filter, Duration timeout);
boolean isConnected();
void close();
}
FixStubRegistry (Layer 1 β FIX Protocol)β
WireMock-like API for configuring exchange stub responses:
// Register a stub: reject AAPL orders with fat-finger prices
stubRegistry.when(msg -> {
try {
return msg.getString(Symbol.FIELD).equals("AAPL")
&& msg.getDecimal(Price.FIELD).doubleValue() > 5000;
} catch (Exception e) {
return false;
}
}).respondWith(req -> FixMessageBuilder.rejectionFor(req, FixVersion.FIX44, "Fat-finger check"))
.describedAs("AAPL fat-finger rejection")
.register();
// Sequential responses: first partial fill, then full fill
stubRegistry.when(msg -> true)
.respondWith(req -> buildPartialFill(req))
.thenRespondWith(req -> buildFill(req))
.withDelay(Duration.ofMillis(100))
.describedAs("Two-phase fill")
.register();
FixMessageBuilder (Layer 1 β FIX Protocol)β
Fluent builder for constructing FIX messages:
// Build a NewOrderSingle (35=D)
Message order = FixMessageBuilder.newOrderSingle(FixVersion.FIX44)
.clOrdId("ORD-001")
.symbol("MSFT")
.side(OrderConfiguration.Side.BUY)
.orderType(OrderConfiguration.OrderType.LIMIT)
.price(BigDecimal.valueOf(305.50))
.quantity(500)
.account("FUND-001")
.timeInForce(OrderConfiguration.TimeInForce.DAY)
.transactTimeNow()
.build();
// Convenience: build from OrderConfiguration
Message order = FixMessageBuilder.fromOrderConfig(config, FixVersion.FIX44);
// Convenience: create rejection/fill ExecutionReports
Message rejection = FixMessageBuilder.rejectionFor(order, FixVersion.FIX44, "Price too high");
Message fill = FixMessageBuilder.fillFor(order, FixVersion.FIX44, BigDecimal.valueOf(305.25));
MarketMaker (Layer 2 β Logic Core)β
Statistical distribution engine for realistic financial test data:
MarketMaker mm = new MarketMaker(BusinessCalendar.nyse());
// Normal (Gaussian) distribution for prices
BigDecimal price = mm.generatePrice(150.0, 2.0);
// Poisson distribution for volumes
int volume = mm.generateVolume(500);
// Cholesky-decomposed correlated price series
List<BigDecimal> prices = mm.generateCorrelatedPrices(100.0, 5.0, 0.8, 20);
// T+N settlement dates (skips weekends + holidays)
LocalDate settle = mm.generateTradeDate(SettlementType.T2);
// Market-hours timestamps (9:30β16:00 ET)
LocalDateTime timestamp = mm.generateTradeTimestamp();
// Unique identifiers
String clOrdId = mm.generateClOrdId(); // "QUANTAF-1738000000-4821"
String account = mm.generateAccountId("FUND"); // "FUND-12345678"
TradeLedger (Layer 2 β Logic Core)β
Cross-source reconciliation engine with three-way comparison:
TradeLedger ledger = new TradeLedger(8, BigDecimal.valueOf(0.0001));
// Add records from all three sources
ledger.addRecord(TradeRecord.fromFix().clOrdId("ORD-1").symbol("AAPL")
.price(price).quantity(qty).amount(amount)
.currency("USD").settlementDate(date));
ledger.addRecord(TradeRecord.fromMq().clOrdId("ORD-1").symbol("AAPL")
.price(price).quantity(qty).amount(amount)
.currency("USD").settlementDate(date));
ledger.addRecord(TradeRecord.fromApi().clOrdId("ORD-1").symbol("AAPL")
.price(price).quantity(qty).amount(amount)
.currency("USD").settlementDate(date));
// Reconcile a single key
ReconciliationResult result = ledger.reconcile("ORD-1");
// Fluent assertion DSL
TradeLedgerAssert.assertThat(result)
.assertParity()
.assertSettlementDateMatch()
.assertAmountMatch(BigDecimal.valueOf(0.01))
.assertFieldMatch("symbol");
// Reconcile all known keys
List<ReconciliationResult> allResults = ledger.reconcileAll();
// Verify rejection handling
boolean rejected = ledger.verifyRejectionHandled("AAPL");
LlmProvider (Layer 3 β AI Cortex)β
Pluggable interface for LLM backends:
public interface LlmProvider {
String complete(String systemPrompt, String userMessage);
String getProviderName();
String getModelName();
boolean isAvailable();
}
Implementations:
| Class | Backend | Key Config |
|---|---|---|
OpenAiProvider | OpenAI via langchain4j-open-ai | API key, model name, temperature=0.1 |
OllamaProvider | Local Ollama via langchain4j-ollama | Base URL (default http://localhost:11434), model name, temperature=0.1 |
Build & Test Commandsβ
./gradlew build # Build without tests
./gradlew build -x test # Explicitly skip tests
./gradlew test # Run all tests
./gradlew test --tests "io.github.vinipx.quantaf.unit.MarketMakerTest" # Specific class
./gradlew allureReport # Generate Allure report
./docs.sh # Serve documentation (http://localhost:3000)
Troubleshootingβ
| Issue | Solution |
|---|---|
| Port 9876/9877 already in use | lsof -ti tcp:9876 | xargs kill |
| Gradle out of memory | Increase JVM args in gradle.properties: org.gradle.jvmargs=-Xmx2048m |
| LLM API errors | Check QUANTAF_AI_API_KEY env var, or ensure fallbackToTemplates: true in quantaf.yml |
| Allure report empty | Verify build/allure-results/ has JSON files after test run |
| mkdocs not found | mkdocs has been replaced by Docusaurus. Run ./docs.sh (requires Node.js β₯ 18) |
| Test flakiness in CI | Statistical tests use large sample sizes (10k) with generous tolerances |