Skip to main content

Configuration Guide

Overview

QUANTAF uses centralized YAML-based configuration loaded at startup by the QuantafConfig singleton. The configuration file supports environment variable interpolation via ${VAR_NAME} syntax and is organized into sections matching the framework's architectural layers.

Main Configuration File

Location: src/main/resources/quantaf.yml

The QuantafConfig class loads this file using Jackson YAML and provides typed accessor objects (fix(), messaging(), rest(), ai(), ledger()).

Complete Configuration Reference

Below is the actual quantaf.yml shipped with QUANTAF, annotated with explanations:

quantaf:
environment: local # local | ci | staging — drives EnvironmentResolver

# ─── Layer 1: FIX Protocol ───────────────────────────────
fix:
defaultVersion: FIX44 # FIX42 | FIX44 | FIX50
sessions:
trader: # Initiator session (sends orders)
senderCompId: QUANTAF_CLIENT
targetCompId: TARGET_PLATFORM
host: localhost
port: 9876
exchange: # Acceptor session (exchange stub)
type: acceptor
senderCompId: QUANTAF_EXCHANGE
targetCompId: TARGET_PLATFORM_OUTBOUND
port: 9877

# ─── Layer 1: Message Queue ──────────────────────────────
messaging:
provider: activemq # activemq | ibmmq | kafka
activemq:
brokerUrl: tcp://localhost:61616
user: admin
password: admin
ibmmq:
host: localhost
port: 1414
queueManager: QM1
channel: DEV.APP.SVRCONN
kafka:
bootstrapServers: localhost:9092

# ─── Layer 1: REST + OAuth2 ──────────────────────────────
rest:
baseUrl: http://localhost:8080/api
oauth2:
tokenUrl: http://localhost:8080/oauth/token
clientId: ${QUANTAF_CLIENT_ID}
clientSecret: ${QUANTAF_CLIENT_SECRET}

# ─── Layer 3: AI / LLM ──────────────────────────────────
ai:
provider: ollama # openai | ollama
model: llama3
baseUrl: http://localhost:11434
apiKey: ${QUANTAF_AI_API_KEY}
fallbackToTemplates: true # Use templates when LLM unavailable
cacheResponses: true # Cache SmartStub responses

# ─── Layer 2: Reconciliation ─────────────────────────────
ledger:
amountPrecision: 8 # Decimal precision for comparisons
defaultTolerance: 0.0001 # Max allowed difference for amounts
timezone: UTC

# ─── Reporting ───────────────────────────────────────────
reporting:
allure:
resultsDir: build/allure-results
attachFixMessages: true
attachMqPayloads: true

Configuration Sections Detail

Environment

quantaf:
environment: local # local | ci | staging

The EnvironmentResolver uses this value to determine runtime behavior:

EnvironmentDetectionBehavior
LOCALDefault, or when no CI env varDocker Compose services expected
CIAuto-detected from CI or GITHUB_ACTIONS env varsTestcontainers used, AI templates forced
STAGINGExplicit configurationConnects to staging infrastructure

The resolver also provides helper methods:

EnvironmentResolver resolver = new EnvironmentResolver("local");
resolver.useDockerCompose(); // true for LOCAL
resolver.useTestcontainers(); // true for CI
resolver.useAiTemplates(); // true for CI

FIX Protocol

Accessed via QuantafConfig.getInstance().fix():

FixConfig fix = config.fix();
String version = fix.getDefaultVersion(); // "FIX44"
String sender = fix.getSenderCompId("trader"); // "QUANTAF_CLIENT"
String target = fix.getTargetCompId("trader"); // "TARGET_PLATFORM"
String host = fix.getHost("trader"); // "localhost"
int port = fix.getPort("trader"); // 9876

Each FIX version also has a dedicated QuickFIX/J configuration file:

FileVersionBeginString
quickfix-FIX42.cfgFIX 4.2FIX.4.2
quickfix-FIX44.cfgFIX 4.4FIX.4.4
quickfix-FIX50.cfgFIX 5.0FIXT.1.1

These files define session-level settings (HeartBtInt, ReconnectInterval, DataDictionary, FileStore/FileLog paths) and are loaded by FixSessionManager.

Message Queue

Accessed via QuantafConfig.getInstance().messaging():

MessagingConfig mq = config.messaging();
String provider = mq.getProvider(); // "activemq"
String brokerUrl = mq.getBrokerUrl(); // "tcp://localhost:61616"

The provider field selects which broker configuration block to use. Currently supported:

ProviderImplementationStatus
activemqActiveMqBroker via Apache Artemis (Jakarta JMS)Fully implemented
ibmmqIbmMqBrokerSkeleton (awaiting IBM MQ client libraries)
kafkaConfiguration placeholder (not yet implemented)

REST + OAuth2

Accessed via QuantafConfig.getInstance().rest():

RestConfig rest = config.rest();
String baseUrl = rest.getBaseUrl(); // "http://localhost:8080/api"
String tokenUrl = rest.getTokenUrl(); // "http://localhost:8080/oauth/token"
String clientId = rest.getClientId(); // resolved from ${QUANTAF_CLIENT_ID}
String clientSecret = rest.getClientSecret();// resolved from ${QUANTAF_CLIENT_SECRET}

The OAuth2TokenManager handles the token lifecycle:

  • Acquires tokens via client_credentials grant
  • Caches tokens in memory
  • Auto-refreshes 60 seconds before expiry
  • Thread-safe via synchronized methods

AI / LLM

Accessed via QuantafConfig.getInstance().ai():

AiConfig ai = config.ai();
String provider = ai.getProvider(); // "ollama"
String model = ai.getModel(); // "llama3"
String baseUrl = ai.getBaseUrl(); // "http://localhost:11434"
String apiKey = ai.getApiKey(); // resolved from ${QUANTAF_AI_API_KEY}
boolean fallback = ai.isFallbackToTemplates(); // true
boolean cache = ai.isCacheResponses(); // true
SettingDefaultPurpose
providerollamaLLM backend: openai or ollama
modelllama3Model identifier
baseUrlhttp://localhost:11434Ollama server URL
apiKeyOpenAI API key (via env var)
fallbackToTemplatestrueUse deterministic templates when LLM unavailable
cacheResponsestrueCache SmartStub ISO 20022 responses
CI Pipeline Strategy

In CI environments, set fallbackToTemplates: true to ensure tests never depend on external LLM availability. The FixScenarioAgent template engine uses keyword-based deterministic generation that produces identical results across runs.

Ledger / Reconciliation

Accessed via QuantafConfig.getInstance().ledger():

LedgerConfig ledger = config.ledger();
int precision = ledger.getAmountPrecision(); // 8
double tolerance = ledger.getDefaultTolerance(); // 0.0001
String tz = ledger.getTimezone(); // "UTC"

These values are passed to the TradeLedger constructor by QuantafBaseTest:

ledger = new TradeLedger(precision, BigDecimal.valueOf(tolerance));

The precision creates a MathContext(8, RoundingMode.HALF_EVEN) for normalizing numeric values before comparison.

Environment Variable Interpolation

The QuantafConfig.resolveEnvVar() method supports ${VAR_NAME} substitution:

# Resolved from environment variable
clientId: ${QUANTAF_CLIENT_ID}

# Falls back to system property, then empty string
apiKey: ${QUANTAF_AI_API_KEY}
No Default Value Syntax

Unlike some frameworks, the current resolveEnvVar() implementation does not support ${VAR:default} syntax with colon-separated defaults. If the environment variable is not set, the value resolves to an empty string. Set all required variables before running tests.

Setting environment variables:

# macOS/Linux
export QUANTAF_CLIENT_ID=my-client
export QUANTAF_CLIENT_SECRET=my-secret
export QUANTAF_AI_API_KEY=sk-...
./gradlew test

# Or inline
QUANTAF_AI_API_KEY=sk-... ./gradlew test

QuickFIX/J Configuration

The FIX session configuration files in src/main/resources/ follow QuickFIX/J format:

# quickfix-FIX44.cfg
[default]
FileStorePath=build/data/quickfix/fix44
FileLogPath=build/logs/quickfix/fix44
ConnectionType=initiator
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ReconnectInterval=5
UseDataDictionary=Y
DataDictionary=FIX44.xml
ValidateUserDefinedFields=N
ValidateIncomingMessage=N

# Trader Session (Initiator)
[session]
BeginString=FIX.4.4
SenderCompID=QUANTAF_CLIENT
TargetCompID=TARGET_PLATFORM
SocketConnectHost=localhost
SocketConnectPort=9876

# Exchange Stub Session (Acceptor)
[session]
ConnectionType=acceptor
BeginString=FIX.4.4
SenderCompID=QUANTAF_EXCHANGE
TargetCompID=TARGET_PLATFORM_OUTBOUND
SocketAcceptPort=9877

Key settings:

SettingValuePurpose
HeartBtInt30Heartbeat interval in seconds
ReconnectInterval5Seconds between reconnection attempts
ValidateIncomingMessageNRelaxed validation for test stubs
FileStorePathbuild/data/quickfix/Session persistence directory
FileLogPathbuild/logs/quickfix/FIX message log directory

Logging Configuration

Location: src/main/resources/logback.xml

<!-- Log levels by component -->
<logger name="io.github.vinipx.quantaf" level="DEBUG"/>
<logger name="quickfix" level="INFO"/>
<logger name="org.apache.activemq" level="WARN"/>

<!-- Output: Console + rolling file (7 day retention) -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>

Log output: build/logs/quantaf.log with daily rotation.

Docker Compose Integration

The docker-compose.yml provides a local ActiveMQ Artemis instance:

# Start ActiveMQ Artemis
docker-compose up -d

# Verify it's running
docker-compose ps

# View web console
open http://localhost:8161 # admin/admin

# Stop
docker-compose down

Services available after docker-compose up:

ServicePortPurpose
ActiveMQ Artemis61616AMQP/OpenWire messaging
ActiveMQ Web Console8161Admin UI (admin/admin)
No Database Required

QUANTAF does not require a database. The TradeLedger stores all records in-memory (LinkedHashMap). The Docker Compose file only starts ActiveMQ Artemis.

Troubleshooting

Configuration Not Loading

  1. Verify quantaf.yml is at src/main/resources/quantaf.yml
  2. Check YAML syntax: python -c "import yaml; yaml.safe_load(open('src/main/resources/quantaf.yml'))"
  3. Check the root key is quantaf: (the config loader reads from this root)

Connection Failures

ErrorCauseSolution
Connection refused on 61616ActiveMQ not runningdocker-compose up -d
Configuration file not foundMissing QuickFIX/J configVerify quickfix-FIX44.cfg in src/main/resources/
OAuth2 token request failedInvalid credentials or token URLCheck QUANTAF_CLIENT_ID and QUANTAF_CLIENT_SECRET
LLM generation failedLLM provider unavailableEnsure fallbackToTemplates: true
API Keys

Never commit API keys to version control. Use environment variables or secure vaults. The quantaf.yml uses ${QUANTAF_AI_API_KEY} placeholder syntax.

Next Steps

  • See Examples for usage patterns with different configurations
  • Review Architecture for how configuration flows through layers
  • Check Development for project structure and extension points