Skip to main content

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:

ClassBackendKey Config
OpenAiProviderOpenAI via langchain4j-open-aiAPI key, model name, temperature=0.1
OllamaProviderLocal Ollama via langchain4j-ollamaBase 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​

IssueSolution
Port 9876/9877 already in uselsof -ti tcp:9876 | xargs kill
Gradle out of memoryIncrease JVM args in gradle.properties: org.gradle.jvmargs=-Xmx2048m
LLM API errorsCheck QUANTAF_AI_API_KEY env var, or ensure fallbackToTemplates: true in quantaf.yml
Allure report emptyVerify build/allure-results/ has JSON files after test run
mkdocs not foundmkdocs has been replaced by Docusaurus. Run ./docs.sh (requires Node.js β‰₯ 18)
Test flakiness in CIStatistical tests use large sample sizes (10k) with generous tolerances