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

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

Tác giả:Những nhà phát minh định lượng - những giấc mơ nhỏ, Tạo: 2024-08-06 14:13:40, Cập nhật: 2024-08-07 15:30:13

[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à sự phối hợp giữa các chiến lược trở nên đặc biệt quan trọng. FMZ ("nền tảng giao dịch định lượng") giúp các nhà giao dịch thực hiện các giao thức giao tiếp giữa các giao dịch chiến lược hiệu quả bằng cách cung cấp các giao thức giao dịch thực và chia sẻ dữ liệu thời gian thực.

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

Cho dù bạn là một người mới bắt đầu giao dịch định lượng FMZ hay 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ế. Hãy cùng chúng tôi khám phá các tính năng mạnh mẽ của FMZ và tìm hiểu cách thực hiện hợp tác hợp tác giữa các chiến lược thông qua các giao thức giao tiếp hiệu quả, nâng cao hiệu quả giao dịch và nắm bắt cơ hội thị trường.


Cảnh tượng nhu cầu

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

Những tình huống nhu cầu này cho thấy nhiều khả năng và lợi thế của giao thức giao tiếp giữa các giao dịch FMZ trong các ứng dụng thực tế. Thông qua giao tiếp giữa các giao dịch chiến lược hiệu quả, các nhà giao dịch có thể ứng phó tốt hơn với môi trường thị trường phức tạp, tối ưu hóa chiến lược giao dịch, nâng cao hiệu quả giao dịch và lợi nhuận.


Giao thức liên lạc FMZ được gói với chức năng Dial

Một khi hiểu được nhu cầu giao tiếp giữa các ổ đĩa thực, bạn phải suy nghĩ về cách thực hiện các nhu cầu này. Không có gì khác ngoài ổ đĩa A mong muốn có thể tương tác với thông tin của ổ đĩa thực B, mặc dù nhu cầu có vẻ đơn giản. Tuy nhiên, có nhiều chi tiết cần phải được thỏa thuận bằng một bộ giao thức giao tiếp, FMZ đã đóng gói một số giao thức giao tiếp phổ biến hơn.

mqtt / nats / amqp / kafka

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

Các kiến trúc liên lạc là:

  • Các dịch vụ (đại diện) Cần phải có một giao thức truyền thông để chuyển tiếp thông điệp giữa người đăng ký và người phát hành. Dịch vụ này có thể được triển khai tại hệ thống của chủ nhà (đối thoại giữa các đĩa thực địa); hoặc có thể là dịch vụ từ xa (đối thoại giữa các đĩa thực tế giữa các máy chủ).
  • Khách hàng (đăng ký, phát hành) Các chương trình trên FMZ có thể được hiểu là khách hàng của một giao thức liên lạc, và các chương trình có thể là người phát hành (pub) hoặc là người đăng ký (sub).

Dial

Khi áp dụng các giao thức này trên nền tảng FMZ, có thể hiểu đơn giản là mqtt / nats / amqp / kafka.Dial()Trong hàm, sử dụngDial()Các chức năng này thực hiện các hoạt động như phát hành tin nhắn, đăng ký. Những tin nhắn được phát hành này được chuyển tiếp qua các đại lý của giao thức, vì vậy trước tiên bạn phải chạy một máy chủ giao thức. Để dễ dàng minh họa, trong các ví dụ sau đây, chúng tôi đã sử dụng các triển khai hình ảnh của các giao thức khác nhau.

Phần tài liệu API trong đó hàm Dial:https://www.fmz.com/syntax-guide#fun_dial

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

img

Sau đó, chúng ta cùng nhau khám phá, thực hành các ứng dụng giao thức liên lạc được hỗ trợ bởi FMZ.


Thực hành giao thức giao tiếp trên đĩa FMZ

mqtt giao thức

MQTT (Message Queuing Telemetry Transport) là một giao thức giao thông thông điệp nhẹ, đặc biệt dành cho môi trường mạng có 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 điểm chính của MQTT: Mô hình phát hành/đăng ký

  • Bài đăng: Các nhà sản xuất tin tức gửi tin tức đến chủ đề.
  • Đăng ký: Người tiêu dùng đăng ký một chủ đề mà họ quan tâm và nhận được tin tức được đăng trên chủ đề đó.
  • Người trung gian: MQTT sử dụng đại lý tin nhắn (Broker) làm trung gian để chuyển tiếp tin nhắn, đảm bảo giải quyết mối quan hệ giữa người phát hành và người đăng ký.

Thông tin và đăng ký

Vì chúng tôi triển khai máy chủ đại diện MQTT bằng phần mềm hỗ trợ giao thức MQTT (eclipse-mosquitto mirror), nên cài đặt trước docker và không nói về sau đó.

Trước khi chạy lệnh triển khai gương, chúng ta cần phải viết một cấu hình proxy server.mosquitto.conf

# 配置端口号及远程访问IP
listener 1883 0.0.0.0
# 设置匿名访问
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 máy chủ đại diện hoạt động, hình ảnh hiển thị như sau:

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 và thực hành nó.

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")
}

Trong mã chiến lược, các hàm Dial được sử dụng chủ yếu:

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

Dial hàm bắt đầu với một số ký tự.mqtt://là tên của giao thức, sau đó theo dõi địa chỉ nghe lén, cổng; ký hiệu "?" sau đó là tên chủ đề đăng ký / phát hành, nơi tên chủ đề thử nghiệm được gọi là:test_topic

Các chiến lược trên được sử dụng để phát hành, đăng ký và thử nghiệm một chủ đề như sau:

img

Bạn cũng có thể sử dụng hai ổ đĩa thực để đăng ký nhau, phát hành thông tin chủ đề, ví dụ như trong chương thực hành của giao thức nats, chúng tôi đã sử dụng ví dụ như vậy, nhưng các giao thức khác không nói về cách này.


Hiệp định nats

NATS là một giao thức đơn giản, dựa trên văn bản phát hành / đăng ký phong cách giao thức. Khách hàng kết nối với gnatsd (NATS máy chủ) và giao tiếp với gnatsd, giao tiếp dựa trên các giao thức TCP / IP thông thường, và xác định một tập hợp nhỏ các hoạt động, thay đổi dòng biểu thị kết thúc.

Mỗi thỏa thuận có những đặc điểm riêng biệt, bạn có thể truy cập các tài liệu cụ thể, thông tin, không được liệt kê ở đây.

Nats Protocol được triển khai tại:

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

Chỉ thị docker này sẽ tự động tải xuống, chạy nats mirror, cổng 4222 là cổng mà khách hàng muốn truy cập.

Listening for client connections on 0.0.0.0:4222
Server is ready

Nats Server Mirror bắt đầu hoạt động, nghe lén cổng 42222.

Truyền thông giữa các thiết bị cục bộ

Chúng ta cần tạo ra hai chính sách (trực tiếp) để đặt tên cho chính sách A và chính sách B, và các mã chính sách này về cơ bản giống nhau.

  • Chiến lược 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()
    }
    
  • Chiến lược 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()
    }
    

Những chiến lược này về cơ bản là giống nhau, chỉ có những điều khác nhau như đăng, đăng ký, đăng chủ đề, đăng chủ đề, đăng thông tin.

Ví dụ như chiến lược B:

  • 1, sử dụngDial()Chức năng tạo đối tượng kết nối máy chủ với máy kháchconnPubCác tin tức được đăng trên Twitter của các thành viên trong nhóm này:

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

    Dòng số tham số của hàm Dial, bắt đầu vớinats://Chỉ sử dụng giao thức Nats để giao tiếp, và sau đóadminlà một thông báo kiểm tra đơn giản được thiết lập khi triển khai Docker Mirrorauth admin, sử dụng ký tự "@" với khoảng nội dung sau đó là địa chỉ dịch vụ và cổng127.0.0.1:4222Và cuối cùng là chủ đề đăng/đăng ký:topic=pubRobotBChú ý, hãy sử dụng dấu "" giữa các địa chỉ trước đây.

  • 2. Sử dụngDial()Chức năng tạo đối tượng kết nối máy chủ với máy kháchconnSubCác bạn có thể đăng ký đăng ký trên trang web này:

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

    Sự khác biệt chỉ làtopic=pubRobotACác chủ đề khác nhau vì cần phải đăng ký chiến lược A để gửi tin nhắnpubRobotA

Tạo và sử dụng các đối tượng đăng ký, phát hành kết nối trong chính sách A tương tự như mô tả ở trên.

  • Chiến lược A hoạt động

    img

  • Chiến lược B hoạt động

    img

Điều này thực hiện một ví dụ đơn giản về giao thức NATS để đăng ký, gửi tin nhắn và giao tiếp giữa đĩa A và đĩa B.


giao thức amqp

Queue của giao thức amqp

Trong giao tiếp không đồng bộ, thông điệp không đến được người nhận ngay lập tức, mà được lưu trữ trong một hộp chứa, sau khi đáp ứng một số điều kiện nhất định, thông điệp sẽ được gửi bởi hộp chứa cho người nhận, hộp chứa này là hàng rào tin nhắn, và để thực hiện chức năng này cần cả hai bên và hộp chứa và các thành phần của nó 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, giao thức này có thể thực hiện giao tiếp không đồng bộ giữa bên gửi và bên nhận.

Mỗi thỏa thuận có những đặc điểm riêng biệt, bạn có thể truy cập các tài liệu cụ thể, thông tin, không được liệt kê ở đây.

Đặt server protocol 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

Docker Mirror sẽ tự động tải xuống và hiển thị sau khi triển khai:

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

Sau khi Mirror Server được triển khai tốt, hãy viết bài kiểm tra ví dụ:

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")
}

Lưu ý rằng hàng đợi sử dụng giao thức amqp sẽ tồn tại trong hàng đợi sau khi phát hành, ví dụ như chúng ta chạy mã ví dụ ở trên một lần đầu tiên. Chúng ta sẽ viết 10 thông báo vào hàng đợi. Sau đó, chúng ta sẽ đọc lại thông tin được viết lần đầu tiên khi chạy lần thứ hai.

img

Bạn có thể thấy hai thông tin nhật ký được trỏ vào mũi tên màu đỏ trong hình ảnh chụp ảnh, thời gian không phù hợp, bởi vì màu đỏ là thông báo được đọc là những thông điệp được viết vào hàng đợi khi mã chính sách được chạy lần đầu tiên.

Một số nhu cầu có thể được thực hiện dựa trên tính năng này, ví dụ: sau khi khởi động lại ổ đĩa thực, vẫn có thể lấy dữ liệu thị trường đã được ghi lại từ hàng đợi để sử dụng cho các hoạt động như tính toán khởi tạo.


Hiệp định Kafka

Apache Kafka là một loại lưu trữ dữ liệu phân tán, được tối ưu hóa để trích xuất và xử lý dữ liệu luồng trong thời gian thực. Dữ liệu luồng là dữ liệu được tạo liên tục từ hàng ngàn nguồn dữ liệu, thường có thể gửi các bản ghi dữ liệu cùng một lúc.

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

  • Đăng và đăng ký lưu trữ
  • Lưu trữ lưu lượng hồ sơ theo thứ tự tạo hồ sơ hiệu quả
  • Xử lý lưu lượng dữ liệu trong thời gian thực

Kafka chủ yếu được sử dụng để xây dựng các ống dẫn và ứng dụng dữ liệu dòng dữ liệu thực tế phù hợp với dòng dữ liệu. Nó kết hợp các chức năng gửi, lưu trữ và xử lý dòng để lưu trữ dữ liệu lịch sử và thời gian thực.

Thông tin và đăng ký

Docker của người đại diện 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

Sử dụng mã thử nghiệm để thử:

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")
}

Chúng ta hãy xem cách sử dụng giao thức Kafka để đăng và đăng ký tin nhắn trong Dial.

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

Như với một số 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 "/" như một khoảng trống, sau đó viết chủ đề đăng ký / xuất bản, nơi chủ đề thử nghiệm được đặt làtest_topic

Kết quả kiểm tra:

img


Thêm nữa