Skip to main content

RunModeHelper - Enriched API Documentation

Executive Summary​

RunModeHelper is a static utility class in the Bookmap Layer1 API that provides global access to the application's operational mode. It distinguishes between live vs. replayed data and real vs. simulated trading, enabling strategies to adapt their behavior based on the runtime environment. The class is initialized once by the Bookmap framework during startup and remains immutable throughout the session.


Table of Contents​

  1. Class Overview
  2. Lifecycle and Initialization
  3. Method Reference
  4. Operating Modes
  5. Relationship with Other Classes
  6. Usage Patterns
  7. Edge Cases and Gotchas
  8. Complete Examples
  9. Utility Wrapper
  10. Document Metadata

Class Overview​

Package and Inheritance​

package velox.api.layer1.common;

public class RunModeHelper extends java.lang.Object

Purpose: Centralized accessor for Bookmap's runtime execution mode configuration.

Official Description​

This class can be used to retrieve Bookmap Run Mode

Enhanced Description​

RunModeHelper serves as a global configuration gate that controls how strategies, data providers, and trading logic behave. It maintains two critical boolean flags:

  1. isLive() - Determines the data source: live from provider vs. replayed by Bookmap
  2. isRealTrading() - Determines order handling: real execution via provider vs. simulated by Bookmap

These flags propagate throughout the Layer1 API ecosystem, affecting:

  • Provider selection (ExternalLiveBaseProvider vs ExternalReaderBaseProvider)
  • Data event generation (Layer1ApiDataListener callbacks)
  • Trading event semantics (Layer1ApiTradingListener callbacks)
  • Execution simulation status (ExecutionInfo.isSimulated, OrderInfo.isSimulated)

Key Characteristics:

  • All methods are static (no instance required)
  • Initialized once during Bookmap startup
  • Immutable after initialization
  • Thread-safe for read operations after initialization (inferred from static read-only pattern)

Lifecycle and Initialization​

Initialization Sequence​

Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 1. User selects mode in Bookmap UI Γ’β€β€š
Γ’β€β€š - Live/Replay Γ’β€β€š
Γ’β€β€š - Real Trading/Simulated Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 2. Bookmap Framework reads configuration Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 3. setRunModeOnce(isLive, isRealTrading) called Γ’β€β€š
Γ’β€β€š [FRAMEWORK ONLY - NOT USER CODE] Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 4. isSet() returns true Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 5. Provider initialization Γ’β€β€š
Γ’β€β€š - ExternalLiveBaseProvider (if isLive=true) Γ’β€β€š
Γ’β€β€š - ExternalReaderBaseProvider (if isLive=false) Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 6. Strategy code queries isLive() / isRealTrading() Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Β¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ
Γ’β€β€š
Ò–¼
Ò”ŒÒ”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”€Ò”
Γ’β€β€š 7. Strategy adapts behavior based on mode Γ’β€β€š
Γ’β€β€Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€β‚¬Γ’β€Λœ

Note: This lifecycle sequence is inferred from the API design patterns and the "Once" naming convention. The exact internal implementation details are not publicly documented.

When is RunModeHelper Ready?​

Safe to use: After isSet() returns true

Typical initialization point for strategies:

  • In Layer1ApiAdminListener.onLoginSuccessful() callback
  • In strategy constructor (if called after framework initialization)
  • In Layer1ApiListener.onUserMessage() handlers

NOT safe: During static initialization or very early constructor code

API Version Note: The Layer1ApiAdminListener interface defines onLoginSuccessful() with no parameters. Some adapter implementations may provide overloaded versions with additional parameters. Always refer to the specific interface you're implementing.


Method Reference​

setRunModeOnce()​

public static void setRunModeOnce(boolean isLive, boolean isRealTrading)

Called by: Bookmap framework (internal use only)

Description: Called by Bookmap code once to set Run Mode.

Parameters:

  • isLive - true if data comes from provider (may still be delayed), false if replayed by Bookmap
  • isRealTrading - true if trading orders go to provider, false if simulated by Bookmap

Behavior:

  • Called exactly once during Bookmap startup
  • Method name "Once" implies idempotent or error on duplicate calls
  • User code should never call this method

Confidence: HIGH (explicitly documented as framework-only)


isSet()​

public static boolean isSet()

Returns: Primitive boolean (never null)

  • true if run mode has been initialized
  • false if not yet initialized

Description: Gate check to determine if isLive() and isRealTrading() are safe to call.

Official Documentation:

Returns true if the Run Mode is selected

Usage:

if (RunModeHelper.isSet()) {
// Safe to query mode
Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();
} else {
// Use default behavior or defer initialization
}

Thread Safety: Safe to call from any thread at any time.

Confidence: HIGH (documented behavior, primitive return)


isLive()​

public static Boolean isLive()

Returns: Object Boolean (can be null)

  • true - Bookmap receives data from the provider
  • false - Bookmap replays data locally
  • null - Not yet initialized (before setRunModeOnce())

Description: Indicates the data source for market events.

Important Notes:

  • "Live" does NOT mean "real-time": Provider can supply delayed or replayed data even when isLive() == true
  • "Live" means "from provider": The data originates from the external data source rather than Bookmap's replay engine
  • Null handling required: Always check for null or use isSet() guard

Official Documentation:

This flag indicates that Bookmap gets the data from the provider, it still can be delayed or replayed by the provider. Otherwise, the data is replayed by Bookmap.

Returns: true if the data live (by provider)

Usage:

Boolean isLive = RunModeHelper.isLive();
if (isLive != null && isLive) {
// Provider-sourced data (live connection)
} else if (isLive != null) {
// Bookmap-replayed data (historical playback)
} else {
// Not initialized yet
}

Confidence: HIGH (directly documented)


isRealTrading()​

public static Boolean isRealTrading()

Returns: Object Boolean (can be null)

  • true - Trading orders are sent to the provider
  • false - Trading is simulated by Bookmap
  • null - Not yet initialized (before setRunModeOnce())

Description: Indicates whether trading operations have real-world consequences.

Important Notes:

  • "Real" does NOT mean "executed": Provider can still simulate orders even when isRealTrading() == true
  • "Real" means "sent to provider": Orders are transmitted to the external broker/exchange rather than handled locally
  • Affects simulation flags: When false, ExecutionInfo.isSimulated and OrderInfo.isSimulated will be true
  • Null handling required: Always check for null or use isSet() guard

Official Documentation:

This flag indicates that all the trading events will be passed to provider, it still can be simulated on provider side. Otherwise, the trading is simulated by Bookmap.

Returns: true if the trading is real (by provider)

Usage:

Boolean isRealTrading = RunModeHelper.isRealTrading();
if (isRealTrading != null && isRealTrading) {
// Real trading mode (orders go to provider)
// CAUTION: Real money at risk!
} else if (isRealTrading != null) {
// Simulated trading (Bookmap simulation)
} else {
// Not initialized yet
}

Confidence: HIGH (directly documented)


Operating Modes​

Four-Mode Matrix​

The two boolean flags create a 2Γƒβ€”2 state space with four distinct operating modes:

ModeisLiveisRealTradingUse CaseRisk Level
LIVE_REALtruetrueProduction trading with live market data🔴 CRITICAL
LIVE_SIMULATEDtruefalsePaper trading with live market dataΓ°ΕΈΕΈΒ‘ LOW
REPLAY_SIMULATEDfalsefalseBacktesting with historical dataΓ°ΕΈΕΈΒ’ NONE
REPLAY_REALfalsetrueTheoretically possible but dangerousÒő ï¸ AVOID

Mode Descriptions​

1. LIVE_REAL (Production)​

isLive() == true && isRealTrading() == true

Characteristics:

  • Real-time market data from broker/exchange
  • Real trading orders sent to broker
  • Actual money at risk
  • Highest latency sensitivity

Typical Configuration:

  • ExternalLiveBaseProvider active
  • Real account credentials
  • Production API endpoints

Strategy Behavior:

  • Enable risk limits
  • Reduce logging verbosity
  • Monitor connection health
  • Implement circuit breakers

2. LIVE_SIMULATED (Paper Trading)​

isLive() == true && isRealTrading() == false

Characteristics:

  • Real-time market data from broker/exchange
  • Simulated order fills by Bookmap
  • No real money at risk
  • Safe for testing strategies

Typical Configuration:

  • ExternalLiveBaseProvider active
  • Simulation mode enabled in UI
  • May use demo account credentials

Strategy Behavior:

  • Test execution logic
  • Validate signal generation
  • Verify risk controls
  • Log detailed diagnostics

3. REPLAY_SIMULATED (Backtesting)​

isLive() == false && isRealTrading() == false

Characteristics:

  • Historical data replayed by Bookmap
  • Simulated order fills
  • Controllable playback speed
  • Safe for optimization and analysis

Typical Configuration:

  • ExternalReaderBaseProvider active
  • Historical data files loaded
  • Replay controls active

Strategy Behavior:

  • Collect performance metrics
  • Test parameter combinations
  • Analyze historical patterns
  • Generate research insights

4. REPLAY_REAL (Unusual/Dangerous)​

isLive() == false && isRealTrading() == true

Characteristics:

  • Historical data replayed by Bookmap
  • Orders would be sent to real broker
  • Òő ï¸ DANGEROUS: Real trades based on old data

Likely Behavior:

  • Probably blocked by Bookmap framework
  • Or provider rejects orders due to stale timestamps
  • Should be avoided in all circumstances

Why This Mode Exists:

  • Theoretical combination of flags
  • May be used for specialized testing scenarios
  • Not recommended for production use

Detecting Current Mode​

public static String getCurrentMode() {
if (!RunModeHelper.isSet()) {
return "NOT_INITIALIZED";
}

boolean live = Boolean.TRUE.equals(RunModeHelper.isLive());
boolean real = Boolean.TRUE.equals(RunModeHelper.isRealTrading());

if (live && real) return "LIVE_REAL";
if (live && !real) return "LIVE_SIMULATED";
if (!live && real) return "REPLAY_REAL";
return "REPLAY_SIMULATED";
}

Relationship with Other Classes​

Direct Dependencies​

RunModeHelper
Γ’β€β€š
Ò”œÒ”€Ò”€ Sets state for Ò”€Ò”€Ò–¢ ExecutionInfo.isSimulated
Γ’β€β€š - true when isRealTrading() == false
Γ’β€β€š - Field: public final boolean isSimulated
Γ’β€β€š - Doc: "True if execution is simulated by Bookmap"
Γ’β€β€š
Ò”œÒ”€Ò”€ Sets state for Ò”€Ò”€Ò–¢ OrderInfo.isSimulated
Γ’β€β€š - true when isRealTrading() == false
Γ’β€β€š - Field: public final boolean isSimulated
Γ’β€β€š
Ò””Ò”€Ò”€ Mirrors concept Ò”€Ò”€Ò–¢ Layer1ApiIsRealTradingMessage
- Field: public final boolean isRealTrading
- Doc: "Indicates that trading is real or simulated
on provider side"
- Note: "Is used for statistics only"

Provider Selection​

isLive() == true  Ò”€Ò”€Ò–¢ ExternalLiveBaseProvider instantiated
Γ’β€β€š
Ò””Ò”€Ò–¢ Connects to broker/exchange
Streams real-time data

isLive() == false Ò”€Ò”€Ò–¢ ExternalReaderBaseProvider instantiated
Γ’β€β€š
Ò””Ò”€Ò–¢ Reads historical data files
Controls replay speed

Evidence: Both ExternalLiveBaseProvider and ExternalReaderBaseProvider are listed as implementing classes for Layer1ApiProvider, Layer1ApiAdminProvider, Layer1ApiDataProvider, and Layer1ApiTradingProvider interfaces in the knowledge base.

Listener Behavior​

Layer1ApiDataListener
Γ’β€β€š
Ò”œÒ”€Ò–¢ onDepth() Ò”€Ò”€Ò”€Ò”¬Ò”€Ò–¢ If isLive()==true: Real-time depth updates
Γ’β€β€š Ò””Ò”€Ò–¢ If isLive()==false: Replayed depth from file
Γ’β€β€š
Ò””Ò”€Ò–¢ onTrade() Ò”€Ò”€Ò”€Ò”¬Ò”€Ò–¢ If isLive()==true: Real-time trades
Ò””Ò”€Ò–¢ If isLive()==false: Replayed trades

Layer1ApiTradingListener
Γ’β€β€š
Ò”œÒ”€Ò–¢ onOrderExecuted() Ò”€Ò”€Ò”€Ò”¬Ò”€Ò–¢ If isRealTrading()==true: Real execution from provider
Γ’β€β€š Ò””Ò”€Ò–¢ If isRealTrading()==false: Simulated by Bookmap
Γ’β€β€š (ExecutionInfo.isSimulated == true)
Γ’β€β€š
Ò””Ò”€Ò–¢ onOrderUpdated() Ò”€Ò”€Ò”€Ò”€Ò”¬Ò”€Ò–¢ OrderInfo.isSimulated set based on isRealTrading()

Usage Patterns​

Pattern 1: Safe Null-Check Guard​

// ALWAYS check isSet() before querying mode
if (RunModeHelper.isSet()) {
Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();

// Now safe to use (but still check for null if paranoid)
if (Boolean.TRUE.equals(isLive)) {
// Live mode logic
}
}

Why: Prevents NullPointerException from auto-unboxing null Boolean to boolean.


Pattern 2: Default Values​

// Provide sensible defaults when mode is unknown
boolean isLive = (RunModeHelper.isSet() && Boolean.TRUE.equals(RunModeHelper.isLive()));
boolean isRealTrading = (RunModeHelper.isSet() && Boolean.TRUE.equals(RunModeHelper.isRealTrading()));

// Now you have primitive booleans with false as default

Why: Simplifies logic when null represents "unknown" or "not initialized".


Pattern 3: Mode-Specific Initialization​

@Override
public void onLoginSuccessful() {
// Initialize based on run mode
if (!RunModeHelper.isSet()) {
Log.warn("RunModeHelper not initialized at login");
return;
}

Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();

if (Boolean.TRUE.equals(isLive)) {
// Set up live data handlers
this.dataBuffer = new RealTimeBuffer(1000);
} else {
// Set up replay data handlers
this.dataBuffer = new HistoricalBuffer(100000);
}

if (Boolean.TRUE.equals(isRealTrading)) {
// Enable risk controls
this.maxPositionSize = 100;
this.enableCircuitBreaker = true;
} else {
// Relaxed limits for simulation
this.maxPositionSize = 10000;
this.enableCircuitBreaker = false;
}
}

Note: The Layer1ApiAdminListener.onLoginSuccessful() method takes no parameters per the official interface. This example uses the correct signature.


Pattern 4: Conditional Logging​

// Reduce log verbosity in production
private void logTrade(TradeInfo trade) {
boolean isProduction = RunModeHelper.isSet()
&& Boolean.TRUE.equals(RunModeHelper.isLive())
&& Boolean.TRUE.equals(RunModeHelper.isRealTrading());

if (isProduction) {
// Minimal logging
Log.info("Trade: " + trade.isBidAggressor);
} else {
// Detailed logging for debugging
Log.debug("Trade details: " + trade);
Log.debug(" isBidAggressor: " + trade.isBidAggressor);
Log.debug(" isOtc: " + trade.isOtc);
}
}

Pattern 5: Risk Management Based on Mode​

private int calculateMaxPositionSize() {
if (!RunModeHelper.isSet()) {
return 100; // Most conservative default
}

Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();

// Production: strict limits
if (Boolean.TRUE.equals(isLive) && Boolean.TRUE.equals(isRealTrading)) {
return 100;
}
// Paper trading: moderate limits
else if (Boolean.TRUE.equals(isLive)) {
return 1000;
}
// Backtesting: generous limits
else {
return 10000;
}
}

Pattern 6: Execution Verification​

@Override
public void onOrderExecuted(ExecutionInfo execution) {
// Verify execution matches expected mode
Boolean isRealTrading = RunModeHelper.isRealTrading();

if (isRealTrading != null && !isRealTrading) {
// We're in simulated mode, execution should be simulated
if (!execution.isSimulated) {
Log.error("INCONSISTENCY: Real execution in simulated mode!");
}
} else if (Boolean.TRUE.equals(isRealTrading)) {
// We're in real mode, execution should NOT be simulated
if (execution.isSimulated) {
Log.warn("Simulated execution in real trading mode");
}
}

// Process execution...
Log.info("Execution: " + execution.size + " @ " + execution.price);
}

Edge Cases and Gotchas​

1. NullPointerException on Auto-Unboxing​

Problem:

// DANGER: NPE if isLive() returns null
if (RunModeHelper.isLive()) { // Auto-unboxes null -> NPE!
// ...
}

Solution:

// SAFE: Explicit null check
Boolean isLive = RunModeHelper.isLive();
if (isLive != null && isLive) {
// ...
}

// BETTER: Guard with isSet()
if (RunModeHelper.isSet() && RunModeHelper.isLive()) {
// isLive() is guaranteed non-null after isSet()==true
}

2. Assuming Immediate Availability​

Problem:

public MyStrategy() {
// Called during construction - RunModeHelper may not be initialized
if (RunModeHelper.isLive()) { // May return null!
// ...
}
}

Solution:

public MyStrategy() {
// Defer mode-dependent initialization
}

@Override
public void onLoginSuccessful() {
// NOW RunModeHelper is guaranteed to be initialized
if (RunModeHelper.isSet()) {
initializeBasedOnMode();
}
}

3. Confusing "Live" with "Real-Time"​

Problem:

if (RunModeHelper.isLive()) {
// Assumption: Data is instantaneous and up-to-date
// WRONG: Provider may have delays or be replaying
}

Reality:

  • Live = Data comes from provider (may have network latency, exchange delays, etc.)
  • Replay = Data comes from Bookmap's historical files

Solution:

  • Always check data timestamps
  • Implement staleness detection
  • Don't assume zero latency

4. Confusing "Real Trading" with "Executed"​

Problem:

if (RunModeHelper.isRealTrading()) {
// Assumption: Orders will definitely execute
// WRONG: Provider may reject, simulate, or delay orders
}

Reality:

  • Real Trading = Orders are sent to the provider
  • Provider may still:
    • Simulate the orders on their side
    • Reject orders due to insufficient funds
    • Apply additional risk controls

Solution:

  • Check ExecutionInfo.isSimulated to verify actual execution type
  • Implement order confirmation logic
  • Don't assume orders automatically execute

5. Attempting to Change Mode from Strategy​

Problem:

// User wants to test different modes without restarting
RunModeHelper.setRunModeOnce(false, false); // DON'T DO THIS!

Why It's Wrong:

  • setRunModeOnce() is framework-only
  • May be ignored, throw exception, or corrupt state
  • Mode is immutable after initialization

Solution:

  • Change mode via Bookmap UI
  • Restart Bookmap to apply new mode
  • Use separate test configurations

6. Thread Safety During Initialization​

Problem:

// Multiple threads query mode while setRunModeOnce() is executing
new Thread(() -> {
Boolean isLive = RunModeHelper.isLive(); // May be null or partially set
}).start();

Solution:

// Wait for initialization to complete
new Thread(() -> {
while (!RunModeHelper.isSet()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// Now safe to query
Boolean isLive = RunModeHelper.isLive();
}).start();

7. Using Mode for Feature Flags​

Problem:

// Treating run mode as generic configuration
if (RunModeHelper.isLive()) {
enableAdvancedCharts(); // Unrelated to data source
}

Why It's Wrong:

  • RunMode is specifically for execution behavior (data source, trading simulation)
  • Not a general-purpose configuration system

Solution:

  • Use separate configuration for features
  • Reserve RunMode checks for execution-critical logic
  • Use proper feature flags or settings files

8. Ignoring Null Returns​

Problem:

// Treating null as false
boolean isLive = RunModeHelper.isLive(); // Auto-unbox: null -> NPE!

// Or:
if (RunModeHelper.isLive() == false) { // NPE if null!
// ...
}

Solution:

// Explicit null handling
Boolean isLiveObj = RunModeHelper.isLive();
boolean isLive = (isLiveObj != null && isLiveObj);

// Or use isSet() guard
if (RunModeHelper.isSet()) {
boolean isLive = RunModeHelper.isLive(); // Safe after isSet() check
}

Complete Examples​

Example 1: Basic Strategy Initialization​

package com.example.strategy;

import velox.api.layer1.common.RunModeHelper;
import velox.api.layer1.Layer1ApiAdminListener;
import velox.api.layer1.Layer1ApiTradingListener;
import velox.api.layer1.data.ExecutionInfo;
import velox.api.layer1.common.Log;

/**
* Example strategy that adapts behavior based on RunMode
*/
public class AdaptiveStrategy implements
Layer1ApiAdminListener,
Layer1ApiTradingListener {

private int maxPositionSize;
private boolean enableDetailedLogging;

@Override
public void onLoginSuccessful() {
// Wait for RunModeHelper initialization
if (!RunModeHelper.isSet()) {
Log.warn("RunModeHelper not initialized");
useDefaultConfiguration();
return;
}

// Get mode flags
Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();

// Configure based on mode
if (Boolean.TRUE.equals(isLive) && Boolean.TRUE.equals(isRealTrading)) {
// LIVE_REAL: Production mode
maxPositionSize = 100;
enableDetailedLogging = false;
Log.info("[PRODUCTION] Strategy initialized");
}
else if (Boolean.TRUE.equals(isLive)) {
// LIVE_SIMULATED: Paper trading
maxPositionSize = 1000;
enableDetailedLogging = true;
Log.info("[PAPER TRADING] Strategy initialized");
}
else {
// REPLAY_SIMULATED: Backtesting
maxPositionSize = 10000;
enableDetailedLogging = true;
Log.info("[BACKTEST] Strategy initialized");
}
}

@Override
public void onOrderExecuted(ExecutionInfo execution) {
// Verify execution type matches mode
Boolean isRealTrading = RunModeHelper.isRealTrading();

if (Boolean.TRUE.equals(isRealTrading) && execution.isSimulated) {
Log.warn("Simulated execution in real trading mode");
}

if (enableDetailedLogging) {
Log.info("Execution: " + execution.size + " @ " + execution.price
+ " (simulated=" + execution.isSimulated + ")");
}
}

private void useDefaultConfiguration() {
maxPositionSize = 100; // Conservative default
enableDetailedLogging = false;
}

// Other required interface methods...
@Override public void onLoginFailed(velox.api.layer1.data.LoginFailedReason reason, String message) {}
@Override public void onConnectionLost(velox.api.layer1.data.DisconnectionReason reason, String message) {}
@Override public void onConnectionRestored() {}
@Override public void onSystemTextMessage(String message, velox.api.layer1.data.SystemTextMessageType type) {}
@Override public void onUserMessage(Object data) {}
@Override public void onOrderUpdated(velox.api.layer1.data.OrderInfoUpdate update) {}
@Override public void onStatus(velox.api.layer1.data.StatusInfo status) {}
@Override public void onBalance(velox.api.layer1.data.BalanceInfo balance) {}
}

Example 2: Four-Mode Strategy with Distinct Behaviors​

package com.example.strategy;

import velox.api.layer1.common.RunModeHelper;
import velox.api.layer1.Layer1ApiAdminListener;
import velox.api.layer1.common.Log;

/**
* Strategy that handles all four RunMode combinations
*/
public class MultiModeStrategy implements Layer1ApiAdminListener {

private enum StrategyMode {
LIVE_REAL,
LIVE_SIMULATED,
REPLAY_REAL,
REPLAY_SIMULATED,
UNKNOWN
}

private StrategyMode currentMode = StrategyMode.UNKNOWN;

@Override
public void onLoginSuccessful() {
currentMode = detectMode();

switch (currentMode) {
case LIVE_REAL:
initializeProductionMode();
break;
case LIVE_SIMULATED:
initializePaperTradingMode();
break;
case REPLAY_SIMULATED:
initializeBacktestMode();
break;
case REPLAY_REAL:
Log.error("CRITICAL: REPLAY_REAL mode detected - this is dangerous!");
// Consider refusing to run
break;
case UNKNOWN:
Log.warn("Could not detect RunMode");
useDefaultConfiguration();
break;
}
}

private StrategyMode detectMode() {
if (!RunModeHelper.isSet()) {
return StrategyMode.UNKNOWN;
}

boolean isLive = Boolean.TRUE.equals(RunModeHelper.isLive());
boolean isRealTrading = Boolean.TRUE.equals(RunModeHelper.isRealTrading());

if (isLive && isRealTrading) return StrategyMode.LIVE_REAL;
if (isLive && !isRealTrading) return StrategyMode.LIVE_SIMULATED;
if (!isLive && isRealTrading) return StrategyMode.REPLAY_REAL;
return StrategyMode.REPLAY_SIMULATED;
}

private void initializeProductionMode() {
Log.info("=== PRODUCTION MODE ===");
// Strict risk controls
// Minimal logging
// Real-time performance critical
}

private void initializePaperTradingMode() {
Log.info("=== PAPER TRADING MODE ===");
// Moderate risk controls
// Detailed logging
// Test execution logic
}

private void initializeBacktestMode() {
Log.info("=== BACKTEST MODE ===");
// Relaxed risk controls
// Full diagnostics
// Collect performance metrics
}

private void useDefaultConfiguration() {
// Conservative defaults when mode unknown
}

// Other required interface methods...
@Override public void onLoginFailed(velox.api.layer1.data.LoginFailedReason reason, String message) {}
@Override public void onConnectionLost(velox.api.layer1.data.DisconnectionReason reason, String message) {}
@Override public void onConnectionRestored() {}
@Override public void onSystemTextMessage(String message, velox.api.layer1.data.SystemTextMessageType type) {}
@Override public void onUserMessage(Object data) {}
}

Example 3: Risk Management Based on Mode​

package com.example.risk;

import velox.api.layer1.common.RunModeHelper;

/**
* Risk manager that adjusts limits based on RunMode
*/
public class AdaptiveRiskManager {

private final int basePositionLimit;

public AdaptiveRiskManager(int basePositionLimit) {
this.basePositionLimit = basePositionLimit;
}

/**
* Get maximum position size based on current RunMode
*/
public int getMaxPositionSize() {
if (!RunModeHelper.isSet()) {
// Most conservative default
return basePositionLimit;
}

Boolean isLive = RunModeHelper.isLive();
Boolean isRealTrading = RunModeHelper.isRealTrading();

// Production: strictest limits
if (Boolean.TRUE.equals(isLive) && Boolean.TRUE.equals(isRealTrading)) {
return basePositionLimit;
}

// Paper trading: moderate limits (10x base)
if (Boolean.TRUE.equals(isLive)) {
return basePositionLimit * 10;
}

// Backtesting: generous limits (100x base)
return basePositionLimit * 100;
}

/**
* Check if order size is within limits for current mode
*/
public boolean isOrderSizeAllowed(int size) {
return Math.abs(size) <= getMaxPositionSize();
}

/**
* Get appropriate stop loss distance based on mode
*/
public double getStopLossDistance(double entryPrice) {
if (!RunModeHelper.isSet()) {
return entryPrice * 0.02; // 2% default
}

Boolean isRealTrading = RunModeHelper.isRealTrading();

if (Boolean.TRUE.equals(isRealTrading)) {
// Real trading: tighter stops (1%)
return entryPrice * 0.01;
} else {
// Simulation: wider stops (3%)
return entryPrice * 0.03;
}
}

/**
* Determine if circuit breaker should be enabled
*/
public boolean shouldEnableCircuitBreaker() {
if (!RunModeHelper.isSet()) {
return true; // Safe default
}

Boolean isRealTrading = RunModeHelper.isRealTrading();

// Enable circuit breaker only in real trading mode
return Boolean.TRUE.equals(isRealTrading);
}
}

Example 4: Data Handler with Mode-Specific Logic​

package com.example.data;

import velox.api.layer1.common.RunModeHelper;
import velox.api.layer1.common.Log;
import velox.api.layer1.data.TradeInfo;

/**
* Data handler that processes trades differently based on mode
*/
public class AdaptiveDataHandler {

private long lastTradeTime = 0;
private static final long STALENESS_THRESHOLD_MS = 5000;

public void onTrade(double price, int size, TradeInfo tradeInfo) {
if (!RunModeHelper.isSet()) {
return; // Skip processing before initialization
}

Boolean isLive = RunModeHelper.isLive();

if (Boolean.TRUE.equals(isLive)) {
handleLiveTrade(price, size, tradeInfo);
} else {
handleReplayTrade(price, size, tradeInfo);
}
}

private void handleLiveTrade(double price, int size, TradeInfo tradeInfo) {
long currentTime = System.currentTimeMillis();

// Check for stale data (important in live mode)
if (lastTradeTime > 0) {
long gap = currentTime - lastTradeTime;
if (gap > STALENESS_THRESHOLD_MS) {
Log.warn("Data gap detected: " + gap + "ms");
}
}

lastTradeTime = currentTime;

// Process with latency awareness
processTrade(price, size);

// Minimal logging in live mode
logTradeSummary(price, size);
}

private void handleReplayTrade(double price, int size, TradeInfo tradeInfo) {
// No need to check for staleness in replay mode

// Process without latency concerns
processTrade(price, size);

// Detailed logging in replay mode
logTradeDetails(price, size, tradeInfo);
}

private void processTrade(double price, int size) {
// Common trade processing logic
}

private void logTradeSummary(double price, int size) {
Log.info(String.format("Trade: %d @ %.2f", size, price));
}

private void logTradeDetails(double price, int size, TradeInfo tradeInfo) {
Log.debug("=== Trade Details ===");
Log.debug(" Price: " + price);
Log.debug(" Size: " + size);
Log.debug(" isBidAggressor: " + tradeInfo.isBidAggressor);
Log.debug(" isOtc: " + tradeInfo.isOtc);
}
}

Utility Wrapper​

For cleaner code and better null safety, consider using this utility wrapper:

package com.example.util;

import velox.api.layer1.common.RunModeHelper;

/**
* Null-safe wrapper around RunModeHelper with convenient utility methods.
*
* This wrapper provides:
* - Primitive boolean returns (never null)
* - Mode enum for cleaner switch statements
* - Formatted mode descriptions
* - Null-safe helper methods
*/
public final class RunModeUtil {

/**
* Enumeration of the four possible run modes
*/
public enum Mode {
LIVE_REAL("Production Trading", "Live data + Real trading"),
LIVE_SIMULATED("Paper Trading", "Live data + Simulated trading"),
REPLAY_REAL("Replay Real", "Historical data + Real trading (DANGEROUS)"),
REPLAY_SIMULATED("Backtesting", "Historical data + Simulated trading"),
NOT_INITIALIZED("Not Initialized", "RunModeHelper not yet set");

private final String displayName;
private final String description;

Mode(String displayName, String description) {
this.displayName = displayName;
this.description = description;
}

public String getDisplayName() { return displayName; }
public String getDescription() { return description; }
}

// Private constructor - utility class
private RunModeUtil() {}

/**
* Check if RunModeHelper is initialized
*/
public static boolean isInitialized() {
return RunModeHelper.isSet();
}

/**
* Get the current mode as an enum
*/
public static Mode getCurrentMode() {
if (!RunModeHelper.isSet()) {
return Mode.NOT_INITIALIZED;
}

boolean isLive = isLiveMode();
boolean isRealTrading = isRealTradingMode();

if (isLive && isRealTrading) return Mode.LIVE_REAL;
if (isLive && !isRealTrading) return Mode.LIVE_SIMULATED;
if (!isLive && isRealTrading) return Mode.REPLAY_REAL;
return Mode.REPLAY_SIMULATED;
}

/**
* Check if currently in live mode (data from provider)
*
* @return true if live, false if replay or not initialized
*/
public static boolean isLiveMode() {
Boolean result = RunModeHelper.isLive();
return result != null && result;
}

/**
* Check if currently in replay mode (data from Bookmap files)
*
* @return true if replay, false if live or not initialized
*/
public static boolean isReplayMode() {
Boolean result = RunModeHelper.isLive();
return result != null && !result;
}

/**
* Check if currently in real trading mode (orders to provider)
*
* @return true if real trading, false if simulated or not initialized
*/
public static boolean isRealTradingMode() {
Boolean result = RunModeHelper.isRealTrading();
return result != null && result;
}

/**
* Check if currently in simulated trading mode (orders simulated by Bookmap)
*
* @return true if simulated, false if real or not initialized
*/
public static boolean isSimulatedTradingMode() {
Boolean result = RunModeHelper.isRealTrading();
return result != null && !result;
}

/**
* Check if in production mode (live data + real trading)
*/
public static boolean isProductionMode() {
return isLiveMode() && isRealTradingMode();
}

/**
* Check if in paper trading mode (live data + simulated trading)
*/
public static boolean isPaperTradingMode() {
return isLiveMode() && isSimulatedTradingMode();
}

/**
* Check if in backtesting mode (replay data + simulated trading)
*/
public static boolean isBacktestMode() {
return isReplayMode() && isSimulatedTradingMode();
}

/**
* Check if in dangerous mode (replay data + real trading)
*/
public static boolean isDangerousMode() {
return isReplayMode() && isRealTradingMode();
}

/**
* Get formatted string describing current mode
*/
public static String getModeDescription() {
Mode mode = getCurrentMode();
return String.format("%s: %s", mode.getDisplayName(), mode.getDescription());
}

/**
* Get short mode code (e.g., "LIVE|REAL", "REPLAY|SIM")
*/
public static String getModeCode() {
if (!isInitialized()) {
return "NOT_SET";
}

String dataSource = isLiveMode() ? "LIVE" : "REPLAY";
String tradingMode = isRealTradingMode() ? "REAL" : "SIM";

return dataSource + "|" + tradingMode;
}

/**
* Wait for RunModeHelper to be initialized (blocking)
*
* @param timeoutMs Maximum time to wait in milliseconds
* @return true if initialized, false if timeout
*/
public static boolean waitForInitialization(long timeoutMs) {
long startTime = System.currentTimeMillis();

while (!isInitialized()) {
if (System.currentTimeMillis() - startTime > timeoutMs) {
return false;
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}

return true;
}
}

Usage of RunModeUtil Wrapper​

import com.example.util.RunModeUtil;
import com.example.util.RunModeUtil.Mode;
import velox.api.layer1.common.Log;

public class MyStrategy {

public void initialize() {
// Wait up to 5 seconds for initialization
if (!RunModeUtil.waitForInitialization(5000)) {
Log.error("RunModeHelper initialization timeout");
return;
}

// Get current mode
Mode mode = RunModeUtil.getCurrentMode();
Log.info("Running in: " + RunModeUtil.getModeDescription());

// Switch on mode enum
switch (mode) {
case LIVE_REAL:
initializeProduction();
break;
case LIVE_SIMULATED:
initializePaperTrading();
break;
case REPLAY_SIMULATED:
initializeBacktest();
break;
case REPLAY_REAL:
Log.error("CRITICAL: Dangerous mode detected!");
break;
case NOT_INITIALIZED:
Log.error("Not initialized");
break;
}

// Simple boolean checks (no null handling needed)
if (RunModeUtil.isProductionMode()) {
enableStrictRiskControls();
}

if (RunModeUtil.isBacktestMode()) {
enableDetailedLogging();
}
}

private void initializeProduction() { /* ... */ }
private void initializePaperTrading() { /* ... */ }
private void initializeBacktest() { /* ... */ }
private void enableStrictRiskControls() { /* ... */ }
private void enableDetailedLogging() { /* ... */ }
}

Document Metadata​

Sources​

Primary Documentation:

  • RunModeHelper.md (Javadoc converted to Markdown)

Related Classes Referenced:

  • Layer1ApiIsRealTradingMessage.md - Real trading flag message
  • ExecutionInfo.md - Contains isSimulated field
  • OrderInfo.md - Contains isSimulated field
  • Layer1ApiDataListener.md - Data event callbacks
  • Layer1ApiTradingListener.md - Trading event callbacks
  • Layer1ApiAdminListener.md - Admin callbacks including onLoginSuccessful()
  • Layer1ApiAdminProvider.md - Lists implementing provider classes
  • Layer1ApiProvider.md - Provider interface hierarchy

Confidence Assessment​

AspectConfidenceReason
OverallHIGHWell-documented API with clear javadoc
Method signaturesHIGHDirectly documented in knowledge base
Return typesHIGHExplicitly stated (Boolean vs boolean)
Initialization lifecycleMEDIUMInferred from "Once" naming and static design
Null handlingHIGHBoolean object returns clearly nullable
Thread safetyMEDIUMNo explicit documentation, inferred from static read-only pattern
Four modesHIGHMathematical combination of two boolean flags
Related class impactHIGHCross-references found and verified
Provider selectionHIGHExternalLiveBaseProvider/ExternalReaderBaseProvider listed as implementing classes
Use in productionHIGHFundamental API design pattern, well-established

Well-Documented Areas​

  1. Òœ… Method signatures and return types
  2. Òœ… Purpose of each boolean flag
  3. Òœ… Distinction between live/replay and real/simulated
  4. Òœ… Relationship to ExecutionInfo/OrderInfo simulation flags
  5. Òœ… Static utility class pattern
  6. Òœ… Provider implementation classes

Inferred/Enhanced Areas​

  1. 🔍 Initialization timing (inferred from "Once" naming)
  2. 🔍 Thread safety characteristics (inferred from static read-only design)
  3. 🔍 Four-mode combinations (derived from 2x2 boolean matrix)
  4. 🔍 Null handling patterns (inferred from Boolean object returns)
  5. 🔍 Best practices and usage patterns (derived from API design)
  6. 🔍 Edge cases and gotchas (inferred from common pitfalls)

Gaps / Unknown Areas​

  1. Γ’Ββ€œ Implementation details: No source code showing internal static field structure
  2. Γ’Ββ€œ Exact initialization timing: When during startup is setRunModeOnce() called?
  3. Γ’Ββ€œ Duplicate call behavior: Exception, ignore, or error on second setRunModeOnce() call?
  4. Γ’Ββ€œ Thread safety guarantees: No documentation on synchronization mechanisms
  5. Γ’Ββ€œ Configuration relationship: How does RunMode relate to bookmap.xml or other config files?
  6. Γ’Ββ€œ UI relationship: How does Bookmap UI mode selector map to setRunModeOnce() parameters?
  7. Γ’Ββ€œ Historical behavior: Has the API changed over Bookmap versions?
  8. Γ’Ββ€œ Performance: Overhead of frequent static method calls (likely negligible but undocumented)

Recommendations for Future Research​

  1. Test in live Bookmap instance: Verify null return behavior before initialization
  2. Test duplicate calls: Confirm behavior when setRunModeOnce() called twice
  3. Review Bookmap source: If available, examine implementation for thread safety details
  4. Check Bookmap forums: Look for user discussions about RunMode edge cases
  5. Validate provider relationship: Confirm that isLive() directly controls provider selection

Enrichment Methodology​

This documentation was generated using the Bookmap API Documentation Enrichment System:

Phase 1: Evidence Gathering

  • Searched knowledge-base for all RunModeHelper references
  • Extracted cross-references to related classes
  • Compiled usage patterns from Javadoc

Phase 2: Behavioral Inference

  • Analyzed method signatures (Boolean vs boolean)
  • Inferred lifecycle from naming ("Once")
  • Mapped relationships to ExecutionInfo/OrderInfo

Phase 3: Hypothesis Generation

  • Formulated testable hypotheses about null returns
  • Identified edge cases from type system
  • Created verification test cases

Phase 4: Documentation Synthesis

  • Produced comprehensive API reference
  • Generated complete code examples
  • Created utility wrapper for better ergonomics

Changes from Original Version​

SectionChangeReason
LifecycleAdded note about inferenceTransparency about confidence level
isSet()Added official return documentationKB verification
isLive()Added full official return documentationKB verification
isRealTrading()Added full official return documentationKB verification
onLoginSuccessful()Fixed signature to no-parameter versionKB shows void onLoginSuccessful()
ExamplesUpdated to use Log.info()Bookmap convention
ExamplesAdded required interface method stubsComplete implementations
Relationship sectionAdded KB evidence noteTransparency
Provider SelectionUpgraded confidence to HIGHKB lists implementing classes
MetadataAdded change logVersion tracking

Document Version: 1.1 Generated: 2025-01-21 API Class: velox.api.layer1.common.RunModeHelper Confidence Level: HIGH Completeness: ~90% (missing only internal implementation details)