리소스 로딩... 로딩...

FMZ를 탐구합니다: 거래 전략 실제 디스크 간 통신 프로토콜의 실습

저자:발명가들의 수량화 - 작은 꿈, 창작: 2024-08-06 14:13:40, 업데이트: 2024-11-05 17:50:35

[TOC]

img

금융시장의 급속한 발전과 양적 거래의 보편화로 인해 점점 더 많은 거래자가 자동화 전략에 의존하기 시작하였다. 이 과정에서 전략 간의 통신과 조정은 특히 중요해졌다. FMZ (quantitative trading platform) 는 효율적인 거래 전략 실제 디스크 통신 프로토콜을 제공함으로써 거래자가 전략의 원활한 연동과 실시간 데이터 공유를 구현하도록 돕는다.

이 기사에서는 FMZ 플랫폼의 거래 전략 실제 디스크 간 통신 프로토콜에 대해 자세히 살펴보고, 그것의 설계 개념, 기능 특징 및 실제 응용에서의 장점을 소개합니다. 우리는 자세한 사례 분석을 통해 이 프로토콜을 사용하여 효율적이고 안정적인 전략 통신을 달성하고 거래 전략의 실행력과 수익 성과를 향상시키는 방법을 보여줍니다.

FMZ의 양적 거래에 대해 처음 접한 애호가이든, 경험이 많은 전문 프로그래머이든, 이 글은 당신에게 귀중한 통찰력과 실용적인 운영 지침을 제공 할 것입니다. 함께 FMZ의 강력한 기능을 탐구하여 효율적인 통신 프로토콜을 통해 전략 간 협력을 구현하고 거래 효율성을 높이고 시장 기회를 포착하는 방법을 알아보자.


수요 시나리오

    1. 다전략적 협업 수요 시나리오: 복잡한 시장 환경에서 단일 전략은 다양한 갑작스러운 상황과 시장 변화에 대응할 수 없을 수 있다. 거래자는 트렌드 추적 전략, 평균 환전 전략, 수권 전략과 같은 여러 전략을 동시에 실행하고 이들 전략들 사이에 실시간 통신을 통해 시장 정보와 거래 신호를 공유하여 전반적인 거래 효율성과 안정성을 향상시키고자 한다.
    1. 시장을 넘나들며 수요 시나리오: 거래자는 다른 거래 시장을 오가며 중소 거래를 하고 싶어 한다. 예를 들어, A주와 상장 시장을 오가며 중소화를 한다. 어떤 시장에서 가격이 이상하면 전략자는 다른 시장의 전략에 적절한 매매 매매를 알리고, 중소 기회를 잡을 수 있도록 해야 한다.
    1. 위험 관리와 헤딩 수요 시나리오: 한 전략은 시장에서 높은 위험과 높은 수익을 창출하는 거래를 찾고 실행하는 것을 담당하고 다른 전략은 전반적인 위험을 모니터링하고 헤딩 작업을 수행하는 데 집중합니다. 이 두 전략은 높은 위험 거래 과정에서 과도한 손실이 발생하지 않도록 하기 위해 실시간 통신과 데이터 공유가 필요합니다.
    1. 분산 거래 시스템 수요 시나리오: 대규모 거래 기관은 거래 시스템의 오류 용도와 성능을 향상시키기 위해 여러 물리적 서버에서 분산 거래 시스템을 운영하고자합니다. 이러한 서버에 대한 전략은 통신 프로토콜을 통해 데이터 동기화 및 조정 작업을 수행하여 전체 거래 시스템의 안정적이고 효율적인 운영을 보장합니다.
    1. 시장 감시와 사전 경고 수요 시나리오: 어떤 전략은 시장의 동력을 실시간으로 모니터링하는 데 특성이 있으며, 시장에서 중대한 변화가 발생했을 때 (비상 또는 급격한 가격 상승과 같은 경우), 전략은 다른 전략에 대응하는 조치를 취하기 위해 신속하게 알릴 필요가 있습니다. 예를 들어 평형, 조정 또는 상승, 위험을 줄이거나 거래 기회를 잡기 위해.
    1. 복합 전략 관리 수요 시나리오: 거래자는 다양한 자산군에 대한 투자를 관리하기 위해 전략의 복합을 사용하며, 각 전략은 특정 자산군 (주식, 채권, 선물 등) 에 초점을 맞추고 있다. 이러한 전략은 포트폴리오 투자를 전체적으로 최적화하고 수익을 극대화하기 위해 의사소통과 조화를 필요로 한다.

이러한 요구 시나리오들은 FMZ 거래 전략 실제 디스크 간 통신 프로토콜의 실제 응용에서의 여러 가능성과 장점을 보여줍니다. 효과적인 전략 간 통신을 통해 거래자는 복잡한 시장 환경에 더 잘 대처하고 거래 전략을 최적화하고 거래 효율성과 수익을 향상시킬 수 있습니다.


FMZ를 포장한 통신 프로토콜과 다이얼 함수

디스크 A와 디스크 B가 상호작용할 수 있기를 바란다는 것만으로도, 겉으로 보기에는 간단하다. 그러나 다양한 세부사항들이 통신 프로토콜을 사용해서 협의해야 하는 것이 있는데, FMZ는 몇 가지 비교적 인기있는 통신 프로토콜을 포장했다.

mqtt / nats / amqp / kafka

통신 구조

통신 구조는 다음과 같습니다.

  • 이 글은 이쪽에서 읽었습니다. 통신 프로토콜을 실행하는 서버를 필요로 하며, 가입자, 발급자 사이의 메시지를 중계한다. 이 서버는 호스팅하는 시스템의 로컬 (현재 디스크 간 통신) 에 배치될 수 있으며, 원격 서비스 (서버 디스크 간 통신) 로도 사용될 수 있다.
  • 클라이언트 (독서자, 게시자) FMZ의 전략 디스크 프로그램은 통신 프로토콜의 클라이언트로 이해할 수 있으며, 전략 디스크는 게시자 (pub) 또는 가입자 (sub) 이 될 수 있습니다.

다이얼 함수

FMZ 플랫폼에서 이러한 프로토콜을 적용할 때 mqtt / nats / amqp / kafka로 간단하게 이해할 수 있습니다.Dial()함수에서, 사용Dial()함수들은 메시지 배포, 구독 등 동작을 수행한다. 이 배포된 메시지는 프로토콜의 서버 텐트 에이전트 (?? 接) 를 통해 구독자의 디스크에 전달된다. 따라서 먼저 프로토콜의 서버를 실행해야 한다. 예시를 위해, 우리는 다음 예제에서 다양한 프로토콜 서버 텐트 미러 배포를 사용한다.

다이얼 함수가 있는 API 문서 섹션:https://www.fmz.com/syntax-guide#fun_dial

도커 미러를 배포하기 전에 먼저 도커 소프트웨어를 설치하는 것을 기억하십시오.

img

다음에는 FMZ가 지원하는 통신 프로토콜의 응용을 함께 탐구하고 실천해보자.


FMZ 플랫폼 실시간 통신 프로토콜 실습

mqtt 프로토콜

MQTT (Message Queuing Telemetry Transport) 는 낮은 대역폭, 높은 지연, 또는 신뢰할 수 없는 네트워크 환경에 특히 적합한 가벼운 메시지 전송 프로토콜이다. 1999년에 IBM의 앤디 스탠퍼드-클라크와 아르렌 닉퍼가 제안하여 ISO 표준 (ISO/IEC PRF 20922) 이 되었다.

MQTT 프로토콜의 주요 특징: 게시/구독 모드

  • 게시물: 뉴스 제작자가 주제에 게시물을 게시합니다.
  • 구독: 뉴스 소비자는 관심있는 주제에 구독하여 해당 주제에 게시된 메시지를 수신합니다.
  • 중개자: MQTT는 메신저 에이전트 (Broker) 를 중개자로 사용하여 게시자와 구독자 사이의 해독을 보장합니다.

뉴스 게시 및 구독

우리는 MQTT 프로토콜을 지원하는 소프트웨어를 사용하는 도커 미러 (eclipse-mosquitto mirror) 를 사용하여 MQTT 프록시 서버를 배포하기 때문에 미리 도커를 설치하고 후속 내용은 설명하지 않습니다.

미러 배포 명령어를 실행하기 전에 우리는 대리 서버 프로파일을 작성해야 합니다.mosquitto.conf

# 配置端口号及远程访问IP
listener 1883 0.0.0.0
# 设置匿名访问
allow_anonymous true

그리고 배포 명령어를 실행합니다:

docker run --rm -p 1883:1883 -v ./mosquitto.conf:/mosquitto/config/mosquitto.conf eclipse-mosquitto

프록시 서버가 실행되면 다음과 같은 것이 표시됩니다.

1723012640: mosquitto version 2.0.18 starting
1723012640: Config loaded from /mosquitto/config/mosquitto.conf.
1723012640: Opening ipv4 listen socket on port 1883.
1723012640: mosquitto version 2.0.18 running

그리고 나서 우리는 전략을 테스트하고 실행할 수 있습니다.

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("当前实盘robotId:", robotId)

    conn = Dial("mqtt://127.0.0.1:1883?topic=test_topic")
    if (!conn) {
        Log("通信失败!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // 写入
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("向testQueue写入消息:", msg)

        // 读取
        Log("read:", conn.read(1000), "#FF0000")

        Sleep(1000)
    }    
}

function onexit() {
    conn.close()
    Log("关闭conn")
}

전략 코드는 주로 다이얼 함수를 사용한다:

Dial("mqtt://127.0.0.1:1883?topic=test_topic")

다이얼 함수의 문자열 변수 시작mqtt://프로토콜 이름, 이어서 경청 주소, 포트, ▲ 기호 "?" 다음 가입/공개 주체의 이름, 여기서 테스트 주체의 이름은 다음과 같습니다.test_topic

이 전략은 게시물, 구독 및 실행 테스트를 위해 다음과 같습니다.

img

또한 두 개의 실제 디스크를 사용하여 서로 가입하거나 주제 정보를 게시할 수 있습니다. 우리는 nats 프로토콜의 연습 섹션에서 이러한 예제를 사용하지만 다른 프로토콜에서는 이러한 방법을 설명하지 않습니다.


nats 협정

NATS의 프로토콜은 간단한, 텍스트 기반의 릴리스/서브스크립션 스타일의 프로토콜이다. 클라이언트는 gnatsd (NATS 서버) 에 연결되고 gnatsd와 통신하며, 통신은 일반적인 TCP/IP 서식어를 기반으로 하며, 매우 작은 작업 세트를 정의하고, 라인 교환을 표시한다. 전통적인, 이진 메시지 형식을 사용하는 메시지 통신 시스템과는 달리, 텍스트 기반의 NATS 프로토콜을 사용하여 클라이언트가 쉽게 구현할 수 있으며, 여러 프로그래밍 언어 또는 스크립트 언어를 편리하게 선택할 수 있습니다.

각 조약은 각기 다른 특성을 가지고 있으며, 구체적인 문서, 자료를 살펴볼 수 있습니다.

Nats 프로토콜 서버를 배포합니다:

docker run name nats rm -p 4222:4222 -p 8222:8222 nats http_port 8222 auth admin

이 도커 명령은 자동으로 nats 이미지를 다운로드하고 실행합니다. 포트 4222는 클라이언트가 액세스하려는 포트입니다.

Listening for client connections on 0.0.0.0:4222
Server is ready

nats 서버미러가 시작되고, 포트 4222를 감시합니다.

로컬 디바이스 리얼 디스크 전략 통신

우리는 두 가지 정책을 만들 필요가 있습니다. (실용 디스크) A 정책과 B 정책이라고 이름 붙여서, 두 가지 정책의 코드는 기본적으로 동일합니다. FMZ 플랫폼에서 가장 쉽게 사용할 수있는 자바스크립트 언어를 사용하여 작성됩니다.

  • 전략 A

    var connPub = null 
    var connSub = null
    
    function main() {
        var robotId = _G()
        Log("当前实盘robotId:", robotId)
    
        connPub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotA")
        if (!connPub) {
            Log("通信失败!")
            return 
        }
    
        connSub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotB")
        if (!connSub) {
            Log("通信失败!")
            return 
        }
    
        while (true) {
            connPub.write("robotA发布的消息,robotId: " + robotId + ", time:" + _D())
            var msgRead = connSub.read(10000)
            if (msgRead) {
                Log("msgRead:", msgRead)
            }
    
            LogStatus(_D())
            Sleep(10000)
        }
    }
    
    function onexit() {
        connPub.close()
        connSub.close()
    }
    
  • 전략 B

    var connPub = null 
    var connSub = null
    
    function main() {
        var robotId = _G()
        Log("当前实盘robotId:", robotId)
    
        connPub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotB")
        if (!connPub) {
            Log("通信失败!")
            return 
        }
    
        connSub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotA")
        if (!connSub) {
            Log("通信失败!")
            return 
        }
    
        while (true) {
            connPub.write("robotB发布的消息,robotId: " + robotId + ", time:" + _D())
            var msgRead = connSub.read(10000)
            if (msgRead) {
                Log("msgRead:", msgRead)
            }
    
            LogStatus(_D())
            Sleep(10000)
        }
    }
    
    function onexit() {
        connPub.close()
        connSub.close()
    }
    

이 두 가지 전략은 기본적으로 동일하지만 서로 게시, 구독, 구독 주제, 게시 주제, 게시 정보는 다릅니다.

예를 들어, 전략 B:

  • 1, 사용Dial()함수 클라이언트 연결 서버 대상 생성connPub이 글은 이 부분의 게시물을 통해 공개되었습니다.

    var connPub = 다이얼127.0.0.1:4222?topic=pubRobotB”)

    다이얼 함수의 변수 문자열, 시작nats://이 문서는 NATS 프로토콜을 사용하는 것을 나타냅니다.admin도커 미러를 배포할 때 설정되는 간단한 확인 정보입니다.auth admin, "@"라는 문자를 사용하여 그 다음의 내용과 간격, 그리고 서비스 주소와 포트를 사용합니다.127.0.0.1:4222그리고 마지막으로, 게시물 / 구독 주제:topic=pubRobotB참고로 이전 주소와 사이에는 "?" 기호가 있습니다.

  • 2, 사용Dial()함수 클라이언트 연결 서버 대상 생성connSub이 글은 이 주제에 대한 뉴스 구독을 위한 것입니다.

    var connSub = 다이얼127.0.0.1:4222?topic=pubRobotA”)

    그 차이점은topic=pubRobotA다른 전략 A를 구독해야 하기 때문에 다른 전략 A를 구독해야 합니다pubRobotA

정책 A의 구독, 게시 연결 개체의 생성 및 사용은 위에서 설명한 것과 동일합니다.

  • 전략 A 실행

    img

  • 전략 B 실행

    img

이렇게 하면 A 디스크와 B 디스크 사이에 상호 구독, 메시지 발송, 통신을 하는 간단한 nats 프로토콜 응용 사례가 구현된다.


amqp 프로토콜

amqp 프로토콜의 queue (열)

비동기 통신에서는 메시지가 즉시 수신자에게 도착하지 않고, 하나의 컨테이너에 저장되며, 특정 조건이 충족되면 메시지는 컨테이너에 의해 수신자에게 전송됩니다. 이 컨테이너는 메시지 큐어입니다. 이 기능을 수행하려면 양쪽과 컨테이너와 그 구성 요소가 통일된 협약과 규칙을 준수해야합니다. AMQP는 이러한 프로토콜입니다.

각 조약은 각기 다른 특성을 가지고 있으며, 구체적인 문서, 자료를 살펴볼 수 있습니다.

amqp 프로토콜 서버를 배포합니다:

docker run rm hostname my-rabbit name rabbit -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=q -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:3-관리

도커 미러를 배포할 때 자동으로 배포를 다운로드하고 완료하면 다음과 같이 표시됩니다.

2024-08-06 09:02:46.248936+00:00 [info] <0.9.0> Time to start RabbitMQ: 15569 ms

서버 이미지 배포가 완료되면 테스트 예제 테스트를 작성합니다.

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("当前实盘robotId:", robotId)

    conn = Dial("amqp://q:admin@127.0.0.1:5672/?queue=robotA_Queue")
    if (!conn) {
        Log("通信失败!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // 读取
        Log("read:", conn.read(1000), "#FF0000")
        
        // 写入
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("向testQueue写入消息:", msg)

        Sleep(1000)
    }    
}

function onexit() {
    conn.close()
    Log("关闭conn")
}

amqp 프로토콜을 사용하는 큐는 게시된 메시지가 큐에 영구적으로 존재한다는 것을 주목해야 합니다. 예를 들어, 위의 예제 코드를 실행하는 동안 큐에 10개의 메시지가 쓰여집니다. 다음으로 두 번째 실행을 할 때 첫 번째 입력된 메시지가 다시 읽혀집니다. 그림은 다음과 같습니다:

img

스크린에서 빨간색 화살표가 가리키는 두 개의 로그 메시지가 시간이 일치하지 않는 것을 볼 수 있습니다. 빨간색으로 표시된 것은 정책 코드가 처음 실행될 때 큐에 쓰인 읽기 메시지가므로입니다.

이 특징에 따라 몇 가지 요구 사항이 실현될 수 있다. 예를 들어: 전략 리얼 디스크가 다시 시작되면, 초기화 컴퓨팅 등의 작업을 위해 큐에서 기록된 시장 데이터를 여전히 얻을 수 있다.


카프카 협정

아파치 카프카 (Apache Kafka) 는 실시간으로 추출하고 처리하기 위해 최적화된 스트림 데이터의 분산 데이터 저장소이다. 스트림 데이터는 수천 개의 데이터 소스에서 지속적으로 생성되는 데이터를 의미합니다. 일반적으로 데이터 기록이 동시에 전송 될 수 있습니다. 스트림 플랫폼은 이러한 지속적인 스트림 데이터를 처리해야하며 순서대로 단계적으로 처리해야합니다.

카프카는 사용자에게 세 가지 주요 기능을 제공합니다.

  • 게시 및 가입 기록 스트림
  • 기록의 생성 순서에 따라 기록 흐름을 효율적으로 저장합니다
  • 실시간으로 기록 흐름을 처리합니다.

카프카는 주로 데이터 흐름에 적응하는 실시간 스트림 데이터 파이프 및 응용 프로그램을 구축하는 데 사용됩니다. 그것은 메시지 송수신, 저장 및 스트림 처리 기능을 결합하여 역사 및 실시간 데이터를 저장할 수 있습니다.

뉴스 게시 및 구독

카프카 대리인을 배포하는 도커 이미지:

docker run --rm --name kafka-server --hostname kafka-server -p 9092:9092 -p 9093:9093 \
        -e KAFKA_CFG_NODE_ID=0 \
        -e KAFKA_CFG_PROCESS_ROLES=controller,broker \
        -e KAFKA_CFG_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 \
        -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
        -e KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT \
        -e KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-server:9093 \
        -e KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER \
        bitnami/kafka:latest

테스트 코드를 사용하여 테스트:

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("当前实盘robotId:", robotId)

    conn = Dial("kafka://localhost:9092/test_topic")
    if (!conn) {
        Log("通信失败!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // 写入
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("向testQueue写入消息:", msg)

        // 读取
        Log("read:", conn.read(1000), "#FF0000")

        Sleep(1000)
    }    
}

function onexit() {
    conn.close()
    Log("关闭conn")
}

이제 우리는 다이얼 함수에서 카프카 프로토콜을 사용하여 메시지를 게시하고 가입하는 방법을 살펴보겠습니다.

Dial("kafka://localhost:9092/test_topic")

다른 몇 가지 프로토콜과 마찬가지로, 프로토콜 이름은 시작됩니다.localhost:9092◎ 다음으로 "/"를 간격으로 사용 하 여, 다음 가입/공개 주제를 작성, 여기 테스트 주제가 설정 됩니다.test_topic

테스트 결과:

img


더 많은