Type/to search
Welcome to FMZ Quant Trading Platform
Programming Languages
JavaScript
TypeScript
Python
C++
MyLanguage
PINE Language
Blockly Visual Programming
Workflow
Key Security
Live Trading
Strategy Library
Docker
Deploy Docker
One-Click Docker Rental
Manual Deployment of Bot
Docker Operation Precautions
Global IP Address Specification
Command Line Parameters for Bot Program
Live Trading Data Migration
Docker Monitor
Exchange
Strategy Editor
Backtesting System
Strategy Entry Functions
Strategy Framework and API Functions
Template Library
Strategy Parameters
Interactive Controls
Options Trading
C++ Strategy Writing Guide
JavaScript Strategy Writing Guide
Web3
Built-in Libraries
Extended API Interface
MCP Service
Trading Terminal
Data Explorer
Alpha Factor Analysis Tool
General Protocol
Debugging Tool
Remote Editing
Import and Export of Complete Strategies
Multi-language Support
Live Trading and Strategy Grouping
Live Trading Display
Strategy Sharing and Renting
Live Trading Message Push
Common Causes of Live Trading Errors and Abnormal Exits
Exchange-Specific Notes

Feature Overview

The inter-strategy live trading communication feature allows different live trading strategies to share data and synchronize states. Through a channel mechanism, one live trading instance can broadcast its state data to other live trading instances, enabling cross-instance, cross-custodian, and cross-server data communication.

Core Concepts

  • Channel: Each live trading instance has an independent channel, with the channel ID being the live trading instance ID
  • Broadcaster: Live trading instance that publishes data on a channel using the SetChannelData() function
  • Subscriber: Live trading instance that subscribes to other live trading instance channel data using the GetChannelData() function
  • State Overwrite: Only the latest state is saved on the channel, new data overwrites old data, not a message queue

Key Features

  • Non-blocking Communication: All function calls are non-blocking and do not affect the main strategy flow
  • Cross-platform Support: Supports data transmission across live trading instances, custodians, and servers
  • Multi-channel Subscription: A single live trading instance can simultaneously subscribe to multiple different live trading instance channels
  • Flexible Data Format: Supports any JSON-serializable data structure

Application Scenarios

  • Master-Slave Strategy Coordination: Master strategy analyzes market and broadcasts signals, slave strategies receive signals and execute trades
  • Multi-account Synchronization: Synchronize trading signals and position information across multiple trading accounts
  • Strategy Monitoring: Monitoring strategies broadcast operational status, monitoring live trading instances subscribe and display or alert
  • Data Sharing: Share market analysis, indicator calculation results to avoid redundant calculations

Basic Usage

Examples

  • Broadcaster Example - Publishing Market Data

    javascript
    function main() { var updateId = 0 var robotId = _G() // Get current live trading ID while(true) { // Get market data var ticker = exchange.GetTicker("BTC_USDT") if (!ticker) { Sleep(5000) continue } // Prepare channel state data var channelState = { robotId: robotId, updateId: ++updateId, timestamp: Date.now(), symbol: "BTC_USDT", lastPrice: ticker.Last, volume: ticker.Volume, high: ticker.High, low: ticker.Low } // Publish latest state on channel (overwrite old state) SetChannelData(channelState) // Display current channel state LogStatus("Channel Broadcaster [Bot ID: " + robotId + "]\n" + "Update ID: #" + channelState.updateId + "\n" + "Time: " + _D(channelState.timestamp) + "\n" + "Symbol: " + channelState.symbol + "\n" + "Last Price: $" + channelState.lastPrice.toFixed(2)) Sleep(60000) // Update channel state every minute } }
    python
    def main(): updateId = 0 robotId = _G() # Get current live trading ID while True: # Get market data ticker = exchange.GetTicker("BTC_USDT") if not ticker: Sleep(5000) continue # Prepare channel state data channelState = { "robotId": robotId, "updateId": updateId + 1, "timestamp": time.time() * 1000, "symbol": "BTC_USDT", "lastPrice": ticker["Last"], "volume": ticker["Volume"], "high": ticker["High"], "low": ticker["Low"] } updateId += 1 # Publish latest state on channel (overwrite old state) SetChannelData(channelState) # Display current channel state LogStatus("Channel Broadcaster [Bot ID: {}]\n".format(robotId) + "Update ID: #{}\n".format(channelState["updateId"]) + "Time: {}\n".format(_D(channelState["timestamp"])) + "Last Price: ${:.2f}".format(channelState["lastPrice"])) Sleep(60000) # Update channel state every minute
    c++
  • Subscriber Example - Subscribe to Multiple Channels

    javascript
    function main() { // Two channel IDs to subscribe to (modify according to actual situation) var channelId1 = "632799" // Live trading ID for channel 1 var channelId2 = "632800" // Live trading ID for channel 2 while(true) { // Subscribe to current state of channel 1 var state1 = GetChannelData(channelId1) // Subscribe to current state of channel 2 var state2 = GetChannelData(channelId2) // Build status display var statusMsg = "Channel Subscriber - Current Subscription Status\n\n" // Display channel 1 status statusMsg += "═══ Channel 1 [" + channelId1 + "] ═══\n" if (state1 !== null) { statusMsg += "Update ID: #" + state1.updateId + "\n" statusMsg += "Time: " + _D(state1.timestamp) + "\n" statusMsg += "Trading Pair: " + state1.symbol + "\n" statusMsg += "Last Price: $" + state1.lastPrice.toFixed(2) + "\n" } else { statusMsg += "Status: Waiting... (first call returns null)\n" } statusMsg += "\n" // Display channel 2 status statusMsg += "═══ Channel 2 [" + channelId2 + "] ═══\n" if (state2 !== null) { statusMsg += "Update ID: #" + state2.updateId + "\n" statusMsg += "Time: " + _D(state2.timestamp) + "\n" statusMsg += "Last Price: $" + state2.lastPrice.toFixed(2) + "\n" } else { statusMsg += "Status: Waiting... (first call returns null)\n" } LogStatus(statusMsg) Sleep(5000) // Subscribe to channels every 5 seconds } }
    python
    def main(): # Two channel IDs to subscribe to (modify according to actual situation) channelId1 = "632799" # Live trading ID for channel 1 channelId2 = "632800" # Live trading ID for channel 2 while True: # Subscribe to current state of channel 1 state1 = GetChannelData(channelId1) # Subscribe to current state of channel 2 state2 = GetChannelData(channelId2) # Build status display statusMsg = "Channel Subscriber - Current Subscription Status\n\n" # Display channel 1 status statusMsg += "═══ Channel 1 [{}] ═══\n".format(channelId1) if state1 is not None: statusMsg += "Update ID: #{}\n".format(state1["updateId"]) statusMsg += "Time: {}\n".format(_D(state1["timestamp"])) statusMsg += "Last Price: ${:.2f}\n".format(state1["lastPrice"]) else: statusMsg += "Status: Waiting... (first call returns None)\n" statusMsg += "\n" # Display channel 2 status statusMsg += "═══ Channel 2 [{}] ═══\n".format(channelId2) if state2 is not None: statusMsg += "Update ID: #{}\n".format(state2["updateId"]) statusMsg += "Time: {}\n".format(_D(state2["timestamp"])) statusMsg += "Last Price: ${:.2f}\n".format(state2["lastPrice"]) else: statusMsg += "Status: Waiting... (first call returns None)\n" LogStatus(statusMsg) Sleep(5000) # Subscribe to channels every 5 seconds
    c++
  • Practical Application Scenarios

    ### Scenario 1: Master-Slave Strategy Coordinated Trading

    Master Strategy (Signal Broadcasting Side)

    javascript
    function main() { var robotId = _G() Log("Main strategy started, Bot ID:", robotId) while(true) { // Analyze market and generate trading signals var records = exchange.GetRecords("BTC_USDT") if (!records || records.length < 20) { Sleep(5000) continue } // Simple moving average strategy var ma5 = TA.MA(records, 5) var ma20 = TA.MA(records, 20) var signal = "HOLD" if (ma5[ma5.length-1] > ma20[ma20.length-1] && ma5[ma5.length-2] <= ma20[ma20.length-2]) { signal = "BUY" } else if (ma5[ma5.length-1] < ma20[ma20.length-1] && ma5[ma5.length-2] >= ma20[ma20.length-2]) { signal = "SELL" } // Broadcast trading signal var signalData = { timestamp: Date.now(), symbol: "BTC_USDT", signal: signal, price: records[records.length-1].Close, ma5: ma5[ma5.length-1], ma20: ma20[ma20.length-1] } SetChannelData(signalData) LogStatus("Main Strategy - Signal Broadcast\n" + "Signal: " + signal + "\n" + "Price: $" + signalData.price.toFixed(2) + "\n" + "MA5: " + signalData.ma5.toFixed(2) + "\n" + "MA20: " + signalData.ma20.toFixed(2)) Sleep(60000) } }
    python
    def main(): robotId = _G() Log("Main strategy started, Bot ID:", robotId) while True: # Analyze market and generate trading signals records = exchange.GetRecords("BTC_USDT") if not records or len(records) < 20: Sleep(5000) continue # Simple moving average strategy ma5 = TA.MA(records, 5) ma20 = TA.MA(records, 20) signal = "HOLD" if ma5[-1] > ma20[-1] and ma5[-2] <= ma20[-2]: signal = "BUY" elif ma5[-1] < ma20[-1] and ma5[-2] >= ma20[-2]: signal = "SELL" # Broadcast trading signal signalData = { "timestamp": time.time() * 1000, "symbol": "BTC_USDT", "signal": signal, "price": records[-1]["Close"], "ma5": ma5[-1], "ma20": ma20[-1] } SetChannelData(signalData) LogStatus("Main Strategy - Signal Broadcast\n" + "Signal: {}\n".format(signal) + "Price: ${:.2f}\n".format(signalData["price"]) + "MA5: {:.2f}\n".format(signalData["ma5"]) + "MA20: {:.2f}".format(signalData["ma20"])) Sleep(60000)
    c++
  • Practical Application Scenarios

    Scenario 1: Master-Slave Strategy Collaborative Trading

    Slave Strategy (Signal Reception and Execution Side)

    javascript
    function main() { var masterRobotId = "632799" // Master strategy live trading ID var lastSignal = null Log("Follower strategy started, subscribing to main strategy:", masterRobotId) while(true) { // Get signal from master strategy var signalData = GetChannelData(masterRobotId) if (signalData === null) { LogStatus("Waiting for main strategy signal...") Sleep(5000) continue } // Check for new signal if (lastSignal !== signalData.signal) { Log("Received new signal:", signalData.signal, "Price:", signalData.price) // Execute trade if (signalData.signal === "BUY") { var ticker = exchange.GetTicker(signalData.symbol) if (ticker) { exchange.Buy(ticker.Last, 0.01) Log("Executing buy, Price:", ticker.Last) } } else if (signalData.signal === "SELL") { var ticker = exchange.GetTicker(signalData.symbol) if (ticker) { exchange.Sell(ticker.Last, 0.01) Log("Executing sell, Price:", ticker.Last) } } lastSignal = signalData.signal } LogStatus("Follower Strategy - Following Main Strategy\n" + "Current Signal: " + signalData.signal + "\n" + "Signal Price: $" + signalData.price.toFixed(2) + "\n" + "Signal Time: " + _D(signalData.timestamp)) Sleep(5000) } }
    python
    def main(): masterRobotId = "632799" # Master strategy live trading ID lastSignal = None Log("Follower strategy started, subscribing to main strategy:", masterRobotId) while True: # Get signal from master strategy signalData = GetChannelData(masterRobotId) if signalData is None: LogStatus("Waiting for main strategy signal...") Sleep(5000) continue # Check for new signal if lastSignal != signalData["signal"]: Log("Received new signal:", signalData["signal"], "Price:", signalData["price"]) # Execute trade if signalData["signal"] == "BUY": ticker = exchange.GetTicker(signalData["symbol"]) if ticker: exchange.Buy(ticker["Last"], 0.01) Log("Executing buy, Price:", ticker["Last"]) elif signalData["signal"] == "SELL": ticker = exchange.GetTicker(signalData["symbol"]) if ticker: exchange.Sell(ticker["Last"], 0.01) Log("Executing sell, Price:", ticker["Last"]) lastSignal = signalData["signal"] LogStatus("Follower Strategy - Following Main Strategy\n" + "Current Signal: {}\n".format(signalData["signal"]) + "Signal Price: ${:.2f}\n".format(signalData["price"]) + "Signal Time: {}".format(_D(signalData["timestamp"]))) Sleep(5000)
    c++
  • Scenario 2: Multi-Strategy Status Monitoring

    Monitoring Strategy

    javascript
    function main() { // List of live trading strategy IDs to monitor var monitorList = ["632799", "632800", "632801"] while(true) { var table = { type: "table", title: "Strategy Running Status Monitor", cols: ["Live ID", "Status", "Last Update", "Trading Pair", "Current Price", "P&L"], rows: [] } for (var i = 0; i < monitorList.length; i++) { var robotId = monitorList[i] var data = GetChannelData(robotId) if (data !== null) { var updateTime = _D(data.timestamp) var timeDiff = Date.now() - data.timestamp var status = timeDiff < 120000 ? "Running" : "Abnormal" table.rows.push([ robotId, status, updateTime, data.symbol || "-", data.lastPrice ? "$" + data.lastPrice.toFixed(2) : "-", data.profit ? data.profit.toFixed(2) + "%" : "-" ]) } else { table.rows.push([ robotId, "Waiting for Data", "-", "-", "-", "-" ]) } } LogStatus("`" + JSON.stringify(table) + "`") Sleep(10000) } }
    python
    def main(): # List of live trading strategy IDs to monitor monitorList = ["632799", "632800", "632801"] while True: table = { "type": "table", "title": "Strategy Running Status Monitor", "cols": ["Live ID", "Status", "Last Update", "Trading Pair", "Current Price", "P&L"], "rows": [] } for robotId in monitorList: data = GetChannelData(robotId) if data is not None: updateTime = _D(data["timestamp"]) timeDiff = time.time() * 1000 - data["timestamp"] status = "Running" if timeDiff < 120000 else "Abnormal" table["rows"].append([ robotId, status, updateTime, data.get("symbol", "-"), "${:.2f}".format(data["lastPrice"]) if "lastPrice" in data else "-", "{:.2f}%".format(data["profit"]) if "profit" in data else "-" ]) else: table["rows"].append([ robotId, "Waiting for Data", "-", "-", "-", "-" ]) LogStatus("`" + json.dumps(table) + "`") Sleep(10000)
    c++
  • API Function Documentation

    SetChannelData(data)

    Function: Publish latest status data on the channel

    Parameters:

    • data: Data to be published, can be any JSON-serializable data structure

    Return Value: None

    Features:

    • Non-blocking call

    • Overwrites previous data, does not accumulate history

    • Automatically uses current live trading ID as channel ID

    Data Length Limit:

    • Must not exceed 1024 bytes after JSON serialization

    • Recommend transmitting only necessary status information

    Detailed Documentation: SetChannelData

    GetChannelData(robotId)

    Function: Subscribe to channel data of specified live trading instance

    Parameters:

    • robotId: Live trading ID to subscribe to (string or number)

    Return Value:

    • Returns null on first call, retry required

    • Returns latest channel data after successful subscription

    Features:

    • Non-blocking call

    • Can subscribe to multiple channels

    • Can subscribe to own channel

    Detailed Documentation: GetChannelData

    Important Notes

    • First Call Returns null: The GetChannelData() function returns null on first call, which is normal behavior. Wait for data synchronization to complete. Recommend implementing null checks in code.

    • Data Overwrite Mechanism: Channel only stores latest status, calling SetChannelData() overwrites previous data. If historical data preservation is needed, subscribers should record it themselves.

    • Non-blocking Characteristics: All channel communication functions are non-blocking and will not affect main strategy execution flow. However, this also means data immediacy cannot be guaranteed.

    • Data Size Limit: Data passed to SetChannelData must not exceed 1024 bytes after JSON serialization. Should only transmit necessary status information such as trading signals, prices, positions and other key data. Avoid transmitting complete candlestick arrays or large amounts of historical data.

    • Live Trading Environment Limitation: Channel communication functionality is primarily designed for live trading environments and may be limited or unavailable in backtesting systems.

    • Live Trading ID Retrieval: Current live trading ID can be obtained through _G() function, or viewed in platform interface.

    • Security Considerations: Channel data may be subscribed to by other authorized live trading instances. Do not transmit sensitive information (such as API keys) through channels.

    Best Practices

    • Reasonable Update Frequency: Set data update frequency based on actual needs, avoid overly frequent updates that waste resources.

    • Data Structure Design: Design clear data structures including necessary metadata (such as timestamps, version numbers, etc.) for easier subscriber processing.

    • Error Handling: Subscribers should handle null return values, broadcasters should ensure correct data format.

    • Status Version Control: Include version numbers or update IDs in data to help subscribers determine if there is new data.

    • Monitoring and Alerting: For critical communication links, recommend implementing timeout monitoring and alerting mechanisms.

    • Testing and Validation: Verify channel communication stability and latency in test environment before formal use.

    • Documentation: Document channel data formats and communication protocols for future maintenance and team collaboration.

See Also