2026-06-23 22:09:06 +08:00
|
|
|
package com.quantai.trader.config;
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
import com.quantai.trader.enums.TraderExecutionMode;
|
2026-06-23 22:09:06 +08:00
|
|
|
import com.quantai.trader.enums.TraderRunMode;
|
|
|
|
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
import static com.quantai.trader.util.TraderNumbers.requiredText;
|
2026-06-23 22:09:06 +08:00
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
@ConfigurationProperties(prefix = "trader")
|
|
|
|
|
public record TraderProperties(
|
|
|
|
|
String serviceName,
|
|
|
|
|
TraderRunMode runMode,
|
|
|
|
|
String symbol,
|
|
|
|
|
Artifact artifact,
|
|
|
|
|
Feedback feedback,
|
|
|
|
|
Execution execution,
|
|
|
|
|
Runtime runtime,
|
|
|
|
|
Outbox outbox,
|
|
|
|
|
Release release,
|
|
|
|
|
Risk risk,
|
|
|
|
|
PositionManager positionManager
|
|
|
|
|
) {
|
|
|
|
|
public TraderProperties {
|
|
|
|
|
serviceName = defaultText(serviceName, "quant-trader-service");
|
|
|
|
|
runMode = runMode == null ? TraderRunMode.SHADOW : runMode;
|
|
|
|
|
symbol = defaultText(symbol, "BTC-USDT-PERP");
|
|
|
|
|
artifact = artifact == null ? new Artifact("trader-v4-btc-p0", "cal-v4-btc-p0", "pm-v4-btc-p0", ".") : artifact;
|
|
|
|
|
feedback = feedback == null ? new Feedback(false) : feedback;
|
|
|
|
|
execution = execution == null ? new Execution(TraderExecutionMode.SHADOW, 3, 1500) : execution;
|
|
|
|
|
runtime = runtime == null ? new Runtime("trader:v4", true, false) : runtime;
|
|
|
|
|
outbox = outbox == null ? new Outbox(true, 5) : outbox;
|
|
|
|
|
release = release == null ? new Release(true, true, true) : release;
|
|
|
|
|
risk = risk == null ? new Risk(new BigDecimal("200"), BigDecimal.ONE, new BigDecimal("500")) : risk;
|
|
|
|
|
positionManager = positionManager == null ? new PositionManager(BigDecimal.ONE, BigDecimal.ONE) : positionManager;
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
private static String defaultText(String value, String defaultValue) {
|
|
|
|
|
return value == null || value.isBlank() ? defaultValue : value;
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Artifact(
|
|
|
|
|
String modelBundleVersion,
|
|
|
|
|
String calibrationBundleVersion,
|
|
|
|
|
String pmConfigVersion,
|
|
|
|
|
String artifactRoot
|
|
|
|
|
) {
|
|
|
|
|
public Artifact {
|
|
|
|
|
modelBundleVersion = requiredText(modelBundleVersion, "artifact.modelBundleVersion");
|
|
|
|
|
calibrationBundleVersion = requiredText(calibrationBundleVersion, "artifact.calibrationBundleVersion");
|
|
|
|
|
pmConfigVersion = requiredText(pmConfigVersion, "artifact.pmConfigVersion");
|
|
|
|
|
artifactRoot = requiredText(artifactRoot, "artifact.artifactRoot");
|
|
|
|
|
}
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Feedback(boolean httpEnabled) {
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Execution(TraderExecutionMode mode, int maxApiErrorCount, long maxExchangeLatencyMs) {
|
|
|
|
|
public Execution {
|
|
|
|
|
mode = mode == null ? TraderExecutionMode.SHADOW : mode;
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Runtime(String redisKeyPrefix, boolean requireRedisForOpenAdd, boolean tradingEnabled) {
|
|
|
|
|
public Runtime {
|
|
|
|
|
redisKeyPrefix = defaultText(redisKeyPrefix, "trader:v4");
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Outbox(boolean enabled, int maxRetryCount) {
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Release(boolean requireReviewForPaper, boolean requireReviewForLiveProbe, boolean activePointerCheckEnabled) {
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record Risk(BigDecimal maxDailyLossBps, BigDecimal maxTotalExposureRatio, BigDecimal minLiquidationBufferBps) {
|
|
|
|
|
public Risk {
|
|
|
|
|
maxDailyLossBps = maxDailyLossBps == null ? new BigDecimal("200") : maxDailyLossBps;
|
|
|
|
|
maxTotalExposureRatio = maxTotalExposureRatio == null ? BigDecimal.ONE : maxTotalExposureRatio;
|
|
|
|
|
minLiquidationBufferBps = minLiquidationBufferBps == null ? new BigDecimal("500") : minLiquidationBufferBps;
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 21:53:22 +08:00
|
|
|
public record PositionManager(BigDecimal maxSingleLegRatio, BigDecimal maxTotalPositionRatio) {
|
|
|
|
|
public PositionManager {
|
|
|
|
|
maxSingleLegRatio = maxSingleLegRatio == null ? BigDecimal.ONE : maxSingleLegRatio;
|
|
|
|
|
maxTotalPositionRatio = maxTotalPositionRatio == null ? BigDecimal.ONE : maxTotalPositionRatio;
|
2026-06-23 22:09:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|