Tài nguyên đang được tải lên... tải...

Khám phá FMZ: Thực hành giao thức giao tiếp giữa các chiến lược giao dịch trực tiếp

Tác giả:FMZ~Lydia, Tạo: 2024-08-08 10:09:21, Cập nhật: 2024-11-05 17:51:27

[TOC]

img

Với sự phát triển nhanh chóng của thị trường tài chính và sự phổ biến của giao dịch định lượng, ngày càng có nhiều nhà giao dịch bắt đầu dựa vào các chiến lược tự động để giao dịch. Trong quá trình này, giao tiếp và phối hợp giữa các chiến lược đặc biệt quan trọng.

Bài viết này sẽ khám phá giao thức giao dịch trực tiếp của các chiến lược giao dịch trong nền tảng FMZ, giới thiệu khái niệm thiết kế, tính năng chức năng và lợi thế của nó trong các ứng dụng thực tế. Thông qua phân tích trường hợp chi tiết, chúng tôi sẽ cho thấy cách sử dụng giao thức này để đạt được giao tiếp chiến lược hiệu quả và ổn định và cải thiện hiệu suất thực hiện và lợi nhuận của các chiến lược giao dịch.

Cho dù bạn là một người đam mê giao dịch định lượng chỉ mới bắt đầu với FMZ hoặc là một lập trình viên chuyên nghiệp có kinh nghiệm, bài viết này sẽ cung cấp cho bạn những hiểu biết có giá trị và hướng dẫn hoạt động thực tế.

Kịch bản nhu cầu

    1. Giao dịch hợp tác đa chiến lược Kịch bản nhu cầu: Trong một môi trường thị trường phức tạp, một chiến lược duy nhất có thể không thể đối phó với các trường hợp khẩn cấp và thay đổi thị trường khác nhau. Các nhà giao dịch muốn chạy nhiều chiến lược cùng một lúc, chẳng hạn như các chiến lược theo dõi xu hướng, các chiến lược đảo ngược trung bình và các chiến lược điều chỉnh, và để các chiến lược này giao tiếp trong thời gian thực để chia sẻ thông tin thị trường và tín hiệu giao dịch, do đó cải thiện hiệu quả giao dịch tổng thể và ổn định.
    1. Thuế trọng tài giữa các thị trường Kịch bản nhu cầu: Các nhà giao dịch muốn thực hiện các giao dịch điều chỉnh giữa các thị trường giao dịch khác nhau. Ví dụ, điều chỉnh bằng cách sử dụng sự khác biệt giá giữa thị trường cổ phiếu A và thị trường chứng khoán Hồng Kông. Khi một sự bất thường giá xảy ra trong một thị trường nhất định, chiến lược cần phải thông báo kịp thời cho các chiến lược trong các thị trường khác để thực hiện các hoạt động mua và bán tương ứng để nắm bắt các cơ hội điều chỉnh.
    1. Quản lý rủi ro và phòng ngừa rủi ro Kịch bản nhu cầu: Một chiến lược chịu trách nhiệm tìm kiếm và thực hiện các giao dịch có rủi ro cao, lợi nhuận cao trên thị trường, trong khi một chiến lược khác tập trung vào việc theo dõi rủi ro tổng thể và thực hiện các hoạt động phòng ngừa rủi ro. Để đảm bảo không có tổn thất quá mức trong các giao dịch có rủi ro cao, hai chiến lược này cần giao tiếp và chia sẻ dữ liệu trong thời gian thực để điều chỉnh các vị trí và phòng ngừa rủi ro kịp thời.
    1. Hệ thống giao dịch phân tán Kịch bản nhu cầu: Các tổ chức giao dịch lớn muốn chạy các hệ thống giao dịch phân tán trên nhiều máy chủ vật lý để cải thiện khả năng chịu lỗi và hiệu suất của hệ thống giao dịch.
    1. Giám sát thị trường và cảnh báo sớm Kịch bản nhu cầu: Một chiến lược chịu trách nhiệm theo dõi theo thời gian thực về động lực thị trường. Khi có những thay đổi lớn trên thị trường (như sự sụt giảm hoặc tăng giá đột ngột), chiến lược cần phải nhanh chóng thông báo cho các chiến lược khác để thực hiện các hành động phản ứng tương ứng, chẳng hạn như đóng các vị trí, điều chỉnh các vị trí hoặc thêm các vị trí, để giảm rủi ro hoặc nắm bắt các cơ hội giao dịch.
    1. Quản lý chiến lược danh mục đầu tư Kịch bản nhu cầu: Các nhà giao dịch sử dụng một danh mục đầu tư của các chiến lược để quản lý đầu tư trong các loại tài sản khác nhau, với mỗi chiến lược tập trung vào một loại tài sản cụ thể (như cổ phiếu, trái phiếu, tương lai, v.v.).

Các kịch bản nhu cầu này chứng minh các khả năng và lợi thế khác nhau của giao thức giao dịch giao dịch trực tiếp trong các ứng dụng thực tế. Thông qua giao tiếp giữa các chiến lược hiệu quả, các nhà giao dịch có thể đối phó tốt hơn với môi trường thị trường phức tạp, tối ưu hóa các chiến lược giao dịch và cải thiện hiệu quả giao dịch và lợi nhuận.

FMZ Protocol truyền thông đóng gói và chức năng quay số

Sau khi hiểu được các yêu cầu giao tiếp giữa các giao dịch trực tiếp, chúng ta cần xem xét cách thực hiện các yêu cầu này. Nó không gì khác ngoài giao dịch trực tiếp A hy vọng trao đổi thông tin với giao dịch trực tiếp B. Mặc dù các yêu cầu có vẻ đơn giản, nhưng có nhiều chi tiết cần phải được đồng ý khi sử dụng một bộ giao thức giao tiếp. FMZ đã kết hợp một số giao thức giao tiếp phổ biến.

mqtt / nats / amqp / kafka

Kiến trúc truyền thông

Kiến trúc truyền thông là:

  • Máy chủ (Proxy). Một máy chủ chạy giao thức truyền thông là cần thiết để chuyển tiếp tin nhắn giữa người đăng ký và nhà xuất bản. Máy chủ này có thể được triển khai cục bộ trên hệ thống dockers (đối với giao tiếp giao dịch trực tiếp địa phương) hoặc như một dịch vụ từ xa (đối với giao tiếp giao dịch trực tiếp giữa máy chủ).
  • Khách hàng (người đăng ký, nhà xuất bản). Chương trình giao dịch trực tiếp chiến lược trên FMZ có thể được hiểu là một khách hàng của một giao thức truyền thông. Chương trình chiến lược thời gian thực có thể là một nhà xuất bản (pub) hoặc một thuê bao (sub).

Chức năng quay số

Khi áp dụng các giao thức này trên nền tảng FMZ, bạn có thể hiểu đơn giản rằng các giao thức mqtt / nats / amqp / kafkap được tích hợp vàoDial()chức năng, vàDial()function được sử dụng để xuất bản và đăng ký tin nhắn. Những tin nhắn được xuất bản này được proxy (chuyển tiếp) đến giao dịch trực tiếp được đăng ký thông qua máy chủ giao thức, vì vậy máy chủ giao thức phải được chạy trước. Để chứng minh, chúng tôi sử dụng các triển khai hình ảnh máy chủ giao thức khác nhau trong các ví dụ sau.

Chức năng quay số trong phần tài liệu API:https://www.fmz.com/syntax-guide#fun_dial

Trước khi triển khai hình ảnh docker, hãy nhớ cài đặt phần mềm docker trước.

img

Tiếp theo, chúng ta hãy khám phá và thực hành các ứng dụng giao thức liên lạc được hỗ trợ bởi FMZ.

FMZ Platform thực hành giao dịch trực tiếp giao dịch giao tiếp

giao thức mqtt

MQTT (Message Queuing Telemetry Transport) là một giao thức truyền thông thông điệp nhẹ đặc biệt phù hợp với môi trường mạng băng thông thấp, độ trễ cao hoặc không đáng tin cậy. Nó được đề xuất bởi Andy Stanford-Clark và Arlen Nipper của IBM vào năm 1999 và sau đó trở thành tiêu chuẩn ISO (ISO / IEC PRF 20922).

Các tính năng chính của giao thức MQTT: chế độ xuất bản/đăng ký

  • Phát hành: Nhà sản xuất tin nhắn gửi tin nhắn đến chủ đề.
  • Đăng ký: Người tiêu dùng tin nhắn đăng ký một chủ đề quan tâm, do đó nhận được các tin nhắn được xuất bản cho chủ đề đó.
  • Trợ lý: MQTT sử dụng một nhà môi giới tin nhắn làm trung gian để chuyển tiếp tin nhắn, đảm bảo tách rời giữa các nhà xuất bản và thuê bao.

Phát hành tin nhắn và đăng ký

Bởi vì chúng tôi sử dụng hình ảnh docker (hình ảnh muỗi nhật thực) của phần mềm hỗ trợ giao thức MQTT để triển khai máy chủ proxy MQTT, chúng tôi đã cài đặt docker trước và sẽ không đi sâu vào chi tiết sau.

Trước khi chạy lệnh để triển khai hình ảnh, chúng tôi cần phải viết một máy chủ proxy cấu hình tệpmosquitto.conf.

# Configure port number and remote access IP
listener 1883 0.0.0.0
# Setting up anonymous access
allow_anonymous true

Sau đó thực hiện lệnh triển khai:

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

Sau khi hình ảnh máy chủ proxy được chạy, sau đây được hiển thị:

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

Sau đó, chúng ta có thể kiểm tra chiến lược để thực hiện nó.

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("Current live trading robotId:", robotId)

    conn = Dial("mqtt://127.0.0.1:1883?topic=test_topic")
    if (!conn) {
        Log("Communication failure!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // Write
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("Write a message to testQueue:", msg)

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

        Sleep(1000)
    }    
}

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

Việc sử dụng chính của chức năng Dial trong mã chiến lược là:

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

Các tham số chuỗi của hàm Dial bắt đầu vớimqtt://, đó là tên giao thức, theo sau là địa chỉ nghe và cổng. Biểu tượng ? được theo sau bởi tên chủ đề đăng ký / xuất bản. Tên chủ đề được kiểm tra ở đây là:test_topic.

Chiến lược trên xuất bản và đăng ký một chủ đề cùng một lúc.

img

Chúng tôi cũng có thể sử dụng hai giao dịch trực tiếp để đăng ký với nhau và xuất bản thông tin chủ đề. Chúng tôi sử dụng một ví dụ như vậy trong phần thực hành giao thức nats, và sẽ không lặp lại phương pháp này trong các giao thức khác.

Nats Nghị định thư

Giao thức NATS là một giao thức kiểu publish/subscribe đơn giản dựa trên văn bản. Khách hàng kết nối với gnatsd (nền chủ NATS) và giao tiếp với gnatsd. Giao tiếp dựa trên các ổ cắm TCP/IP thông thường và xác định một tập hợp rất nhỏ các hoạt động. Newline chỉ ra kết thúc. Không giống như các hệ thống truyền thông tin nhắn truyền thống sử dụng định dạng tin nhắn nhị phân, giao thức NATS dựa trên văn bản làm cho việc thực hiện khách hàng rất đơn giản và có thể dễ dàng được thực hiện trong nhiều ngôn ngữ lập trình hoặc ngôn ngữ kịch bản.

Mỗi Nghị định thư có đặc điểm riêng của nó. Bạn có thể tham khảo các tài liệu và tài liệu cụ thể, mà sẽ không được chi tiết ở đây.

Xây dựng máy chủ giao thức NATS:

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

Điều này sẽ tự động tải xuống và chạy hình ảnh nats, và cổng 4222 là cổng mà khách hàng cần truy cập. Sau khi hình ảnh được triển khai, một màn hình http cũng sẽ được mở trên cổng 8222.

Listening for client connections on 0.0.0.0:4222
Server is ready

Hình ảnh máy chủ Nats bắt đầu chạy, nghe trên cổng 4222.

Truyền thông giữa các chiến lược giao dịch trực tiếp thiết bị địa phương

Chúng ta cần tạo ra hai chiến lược (giao dịch trực tiếp), hãy đặt tên cho chúng là Chiến lược A và Chiến lược B. Mã của hai chiến lược này về cơ bản là giống nhau. Chúng được viết bằng Javascript, đó là ngôn ngữ dễ sử dụng nhất trên nền tảng FMZ.

  • Chiến lược A
var connPub = null 
var connSub = null

function main() {
    var robotId = _G()
    Log("Current live trading robotId:", robotId)

    connPub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotA")
    if (!connPub) {
        Log("Communication failure!")
        return 
    }

    connSub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotB")
    if (!connSub) {
        Log("Communication failure!")
        return 
    }

    while (true) {
        connPub.write("Message posted by 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()
}
  • Chiến lược B
var connPub = null 
var connSub = null

function main() {
    var robotId = _G()
    Log("Current live trading robotId:", robotId)

    connPub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotB")
    if (!connPub) {
        Log("Communication failure!")
        return 
    }

    connSub = Dial("nats://admin@127.0.0.1:4222?topic=pubRobotA")
    if (!connSub) {
        Log("Communication failure!")
        return 
    }

    while (true) {
        connPub.write("Message posted by 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()
}

Hai chiến lược này gần như giống nhau, ngoại trừ việc chúng xuất bản và đăng ký với nhau, và các chủ đề đăng ký, các chủ đề được xuất bản và thông tin được xuất bản khác nhau.

Hãy lấy chiến lược B làm ví dụ:

    1. Sử dụngDial()chức năng để tạo đối tượng máy chủ kết nối khách hàngconnPubđối với việc xuất bản tin nhắn chủ đề:

var connPub = Dial(nats://admin@127.0.0.1:4222?topic=pubRobotB”)

Dòng tham số của hàm Dial bắt đầu vớinats://chỉ ra rằng giao thức NATS được sử dụng để liên lạc.adminlà thông tin xác minh đơn giảnauth adminđược thiết lập khi triển khai hình ảnh Docker. ký tự @ được sử dụng để tách nội dung sau. Sau đó là địa chỉ dịch vụ và cổng127.0.0.1:4222Cuối cùng, có chủ đề xuất bản/đăng ký:topic=pubRobotBLưu ý rằng ký hiệu ? được sử dụng để tách nó khỏi địa chỉ trước đó.

    1. Sử dụngDial()chức năng để tạo đối tượng máy chủ kết nối khách hàngconnSubcho đăng ký tin nhắn chủ đề:

var connSub = Dial(nats://admin@127.0.0.1:4222?topic=pubRobotA”)

Sự khác biệt duy nhất làtopic=pubRobotA, bởi vì chúng ta cần phải đăng ký chủ đềpubRobotAnơi chiến lược A gửi thông tin.

Việc tạo và sử dụng các đối tượng kết nối đăng ký và xuất bản trong chiến lược A giống như được mô tả ở trên.

  • Chiến lược A chạy

img

  • Chiến lược B chạy

img

Bằng cách này, một ví dụ đơn giản về ứng dụng giao thức NATS được thực hiện trong đó giao dịch trực tiếp A và giao dịch trực tiếp B đăng ký và xuất bản tin nhắn để giao tiếp với nhau.

Nghị định thư amqp

Đường hàng giao thức amqp

Trong giao tiếp không đồng bộ, thông điệp sẽ không đến được người nhận ngay lập tức, nhưng nó sẽ được lưu trữ trong một container. Khi các điều kiện nhất định được đáp ứng, thông điệp sẽ được gửi đến người nhận bởi container. Container này là hàng đợi tin nhắn. Để hoàn thành chức năng này, cả hai bên và container và các thành phần của nó phải tuân thủ các thỏa thuận và quy tắc thống nhất. AMQP là một giao thức như vậy. Cả người gửi và người nhận thông điệp đều có thể thực hiện giao tiếp không đồng bộ bằng cách tuân thủ giao thức này.

Mỗi Nghị định thư có đặc điểm riêng của nó. Bạn có thể tham khảo các tài liệu và tài liệu cụ thể, mà sẽ không được chi tiết ở đây.

triển khai máy chủ giao thức 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-management

Khi triển khai một hình ảnh docker, nó sẽ tải xuống và triển khai tự động, và khi hoàn thành nó sẽ hiển thị:

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

Sau khi hình ảnh máy chủ được triển khai, hãy viết một ví dụ thử nghiệm:

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("Current live trading robotId:", robotId)

    conn = Dial("amqp://q:admin@127.0.0.1:5672/?queue=robotA_Queue")
    if (!conn) {
        Log("Communication failure!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // Read
        Log("read:", conn.read(1000), "#FF0000")
        
        // Write
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("Write a message to testQueue:", msg)

        Sleep(1000)
    }    
}

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

Khi sử dụng hàng đợi giao thức AMQP, xin lưu ý rằng các tin nhắn được xuất bản sẽ tồn tại trong hàng đợi. Ví dụ, nếu chúng ta chạy mã ví dụ trên, 10 tin nhắn sẽ được ghi vào hàng đợi. Sau đó khi chúng ta chạy lần thứ hai, chúng ta có thể thấy rằng tin nhắn được viết lần đầu tiên sẽ được đọc lại khi đọc. Như được hiển thị trong hình:

img

Chúng ta có thể thấy rằng hai tin nhắn nhật ký được chỉ bởi các mũi tên màu đỏ trong ảnh chụp màn hình có thời gian không nhất quán. Lý do là vì tin nhắn màu đỏ là một trong những được đọc và viết vào hàng đợi khi mã chiến lược lần đầu tiên được chạy.

Dựa trên tính năng này, một số yêu cầu có thể được đáp ứng. ví dụ, sau khi chiến lược được khởi động lại, dữ liệu thị trường được ghi lại vẫn có thể được lấy từ hàng đợi để tính toán khởi tạo và các hoạt động khác.

Nghị định thư Kafka

Apache Kafka là một bộ lưu trữ dữ liệu phân tán được tối ưu hóa để hấp thụ và xử lý dữ liệu trực tuyến trong thời gian thực. Dữ liệu trực tuyến là dữ liệu được liên tục tạo ra bởi hàng ngàn nguồn dữ liệu, thường gửi các bản ghi dữ liệu đồng thời. Một nền tảng trực tuyến cần xử lý dòng dữ liệu liên tục này, xử lý nó theo trình tự và gia tăng.

Kafka cung cấp ba chức năng chính cho người dùng:

  • Xuất bản và đăng ký các luồng bản ghi
  • Cung cấp hiệu quả một luồng các bản ghi theo thứ tự chúng được tạo ra
  • Xử lý luồng ghi lại trong thời gian thực

Kafka chủ yếu được sử dụng để xây dựng các đường ống truyền dữ liệu thời gian thực và các ứng dụng thích nghi với luồng dữ liệu. Nó kết hợp các khả năng nhắn tin, lưu trữ và xử lý luồng, và có thể lưu trữ dữ liệu lịch sử và thời gian thực.

Phát hành tin nhắn và đăng ký

Xây dựng hình ảnh docker của proxy 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

Kiểm tra bằng mã kiểm tra:

var conn = null

function main() {
    LogReset(1)
    var robotId = _G()
    Log("Current live trading robotId:", robotId)

    conn = Dial("kafka://localhost:9092/test_topic")
    if (!conn) {
        Log("Communication failure!")
        return 
    }

    for (var i = 0; i < 10; i++) {
        // Write
        var msg = "i: " + i + ", testQueue, robotA, robotId: " + robotId + ", time:" + _D()        
        conn.write(msg)
        Log("Write a message to testQueue:", msg)

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

        Sleep(1000)
    }    
}

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

Hãy xem làm thế nào để sử dụng giao thức Kafka để xuất bản và đăng ký tin nhắn trong chức năng Dial.

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

Giống như các giao thức khác, phần đầu tiên là tên giao thức.localhost:9092. Sau đó sử dụng ký hiệu / làm phân tách, tiếp theo là chủ đề đăng ký / xuất bản.test_topic.

Kết quả thử nghiệm:

img


Thêm nữa