Skip to main content

GuardSystem

Guard system that validates whether a new order can be placed. Guards are checked in sequence: 1. Position Check - Must be flat 2. Active Orders Check - No orders pending 3. Cooldown Check - Cooldown period must have passed All guards must pass for an order to be allowed.

GuardSystem.java
package com.bookmap.ordermanagement.core;

import com.bookmap.ordermanagement.model.GuardResult;
import velox.api.layer1.common.Log;

import java.time.Duration;

/**
* Guard system that validates whether a new order can be placed.
*
* Guards are checked in sequence:
* 1. Position Check - Must be flat
* 2. Active Orders Check - No orders pending
* 3. Cooldown Check - Cooldown period must have passed
*
* All guards must pass for an order to be allowed.
*/
public class GuardSystem {

// Configuration
private final String logPrefix;
private final boolean loggingEnabled;
private long cooldownMs;

// Cooldown state
private volatile long cooldownEndTime;
private volatile long lastTradeCloseTime;

/**
* Creates a new guard system.
*
* @param logPrefix Prefix for log messages
* @param loggingEnabled Whether to enable detailed logging
* @param cooldownDuration Cooldown period after trade closes
*/
public GuardSystem(String logPrefix, boolean loggingEnabled, Duration cooldownDuration) {
this.logPrefix = logPrefix;
this.loggingEnabled = loggingEnabled;
this.cooldownMs = cooldownDuration.toMillis();
this.cooldownEndTime = 0;
this.lastTradeCloseTime = 0;
}

// =========================================================================
// Main Guard Check
// =========================================================================

/**
* Checks all guards to determine if an order can be placed.
*
* @param positionTracker The position tracker
* @param orderRegistry The order registry
* @return GuardResult indicating if order is allowed
*/
public GuardResult canPlaceOrder(PositionTracker positionTracker, OrderRegistry orderRegistry) {

// Guard 1: Position Check
if (!positionTracker.isFlat()) {
GuardResult result = GuardResult.block("PositionGuard",
String.format("Already in position: %s",
positionTracker.isLong() ? "LONG" : "SHORT"));
logGuardResult(result);
return result;
}

// Guard 2: Active Orders Check
if (orderRegistry.hasActiveOrders()) {
GuardResult result = GuardResult.block("ActiveOrdersGuard",
String.format("Active orders pending: %d", orderRegistry.getActiveOrderCount()));
logGuardResult(result);
return result;
}

// Guard 3: Cooldown Check
if (isCooldownActive()) {
long remainingMs = getCooldownRemaining();
GuardResult result = GuardResult.block("CooldownGuard",
String.format("Cooldown active: %d seconds remaining", remainingMs / 1000));
logGuardResult(result);
return result;
}

// All guards passed
GuardResult result = GuardResult.allow();
if (loggingEnabled) {
Log.info(String.format("%s Guard check: ALLOWED", logPrefix));
}
return result;
}

/**
* Logs a guard result if logging is enabled.
*/
private void logGuardResult(GuardResult result) {
if (loggingEnabled && result.isBlocked()) {
Log.info(String.format("%s Guard check: %s", logPrefix, result.toLogMessage()));
}
}

// =========================================================================
// Cooldown Management
// =========================================================================

/**
* Starts the cooldown timer.
* Called when a trade closes.
*/
public void startCooldown() {
this.lastTradeCloseTime = System.currentTimeMillis();
this.cooldownEndTime = this.lastTradeCloseTime + cooldownMs;

if (loggingEnabled) {
Log.info(String.format("%s Cooldown started: %d seconds",
logPrefix, cooldownMs / 1000));
}
}

/**
* Returns true if cooldown is currently active.
*/
public boolean isCooldownActive() {
if (cooldownMs <= 0) return false;
return System.currentTimeMillis() < cooldownEndTime;
}

/**
* Returns the remaining cooldown time in milliseconds.
*/
public long getCooldownRemaining() {
if (!isCooldownActive()) return 0;
return cooldownEndTime - System.currentTimeMillis();
}

/**
* Returns the remaining cooldown time in seconds.
*/
public int getCooldownRemainingSeconds() {
return (int) (getCooldownRemaining() / 1000);
}

/**
* Clears the cooldown timer.
*/
public void clearCooldown() {
cooldownEndTime = 0;
if (loggingEnabled) {
Log.info(String.format("%s Cooldown cleared", logPrefix));
}
}

// =========================================================================
// Configuration
// =========================================================================

/**
* Sets the cooldown duration.
*
* @param duration The cooldown duration
*/
public void setCooldownDuration(Duration duration) {
this.cooldownMs = duration.toMillis();
}

/**
* Gets the cooldown duration in milliseconds.
*/
public long getCooldownMs() {
return cooldownMs;
}

/**
* Gets the last trade close time.
*/
public long getLastTradeCloseTime() {
return lastTradeCloseTime;
}

// =========================================================================
// Reset
// =========================================================================

/**
* Resets all guard state.
*/
public void reset() {
cooldownEndTime = 0;
lastTradeCloseTime = 0;

if (loggingEnabled) {
Log.info(String.format("%s Guard system reset", logPrefix));
}
}

// =========================================================================
// Status
// =========================================================================

/**
* Returns a status summary.
*/
public String getStatusSummary() {
if (isCooldownActive()) {
return String.format("Cooldown: %d seconds remaining", getCooldownRemainingSeconds());
}
return "Ready";
}

@Override
public String toString() {
return getStatusSummary();
}
}