Ngôn ngữ lập trình tốt nhất cho hệ thống giao dịch thuật toán?

Tác giả:Tốt, Tạo: 2019-02-12 10:33:36, Cập nhật:

Một trong những câu hỏi thường gặp nhất mà tôi nhận được trong túi thư là Đâu là ngôn ngữ lập trình tốt nhất cho giao dịch thuật toán?. Câu trả lời ngắn gọn là không có ngôn ngữ best. Các thông số chiến lược, hiệu suất, tính mô-đun, phát triển, khả năng phục hồi và chi phí phải được xem xét. Bài viết này sẽ phác thảo các thành phần cần thiết của kiến trúc hệ thống giao dịch thuật toán và cách các quyết định liên quan đến việc thực hiện ảnh hưởng đến việc lựa chọn ngôn ngữ.

Đầu tiên, các thành phần chính của một hệ thống giao dịch thuật toán sẽ được xem xét, chẳng hạn như các công cụ nghiên cứu, tối ưu hóa danh mục đầu tư, quản lý rủi ro và công cụ thực hiện. Sau đó, các chiến lược giao dịch khác nhau sẽ được kiểm tra và làm thế nào chúng ảnh hưởng đến thiết kế của hệ thống. Đặc biệt, tần suất giao dịch và khối lượng giao dịch có khả năng sẽ được thảo luận.

Một khi chiến lược giao dịch đã được lựa chọn, cần thiết phải kiến trúc toàn bộ hệ thống. Điều này bao gồm sự lựa chọn phần cứng, hệ điều hành và khả năng phục hồi của hệ thống chống lại các sự kiện hiếm gặp, có khả năng gây thảm họa. Trong khi kiến trúc đang được xem xét, phải chú ý đến hiệu suất - cả các công cụ nghiên cứu cũng như môi trường thực thi trực tiếp.

Hệ thống giao dịch đang cố gắng làm gì?

Trước khi quyết định ngôn ngữ tốt nhất để viết một hệ thống giao dịch tự động, cần xác định các yêu cầu. Hệ thống sẽ hoàn toàn dựa trên việc thực hiện? Hệ thống sẽ yêu cầu một mô-đun quản lý rủi ro hoặc xây dựng danh mục đầu tư? Hệ thống sẽ yêu cầu một backtester hiệu suất cao? Đối với hầu hết các chiến lược, hệ thống giao dịch có thể được chia thành hai loại: Nghiên cứu và tạo tín hiệu.

Nghiên cứu liên quan đến việc đánh giá hiệu suất chiến lược trên dữ liệu lịch sử. Quá trình đánh giá chiến lược giao dịch trên dữ liệu thị trường trước đó được gọi là backtesting. Kích thước dữ liệu và độ phức tạp của thuật toán sẽ có tác động lớn đến cường độ tính toán của backtester. Tốc độ CPU và đồng thời thường là các yếu tố hạn chế trong việc tối ưu hóa tốc độ thực hiện nghiên cứu.

Sản xuất tín hiệu liên quan đến việc tạo ra một tập hợp các tín hiệu giao dịch từ một thuật toán và gửi các lệnh đó đến thị trường, thường thông qua môi giới. Đối với một số chiến lược nhất định, một mức độ hiệu suất cao là cần thiết. Các vấn đề I / O như băng thông mạng và độ trễ thường là yếu tố hạn chế trong việc tối ưu hóa hệ thống thực thi. Do đó, việc lựa chọn ngôn ngữ cho từng thành phần của toàn bộ hệ thống của bạn có thể khá khác nhau.

Loại, tần suất và khối lượng chiến lược

Loại chiến lược thuật toán được sử dụng sẽ có tác động đáng kể đến thiết kế của hệ thống. Nó sẽ cần phải xem xét các thị trường được giao dịch, kết nối với các nhà cung cấp dữ liệu bên ngoài, tần suất và khối lượng của chiến lược, sự cân bằng giữa sự dễ dàng phát triển và tối ưu hóa hiệu suất, cũng như bất kỳ phần cứng tùy chỉnh nào, bao gồm các máy chủ tùy chỉnh, GPU hoặc FPGA có thể cần thiết.

Các lựa chọn công nghệ cho một chiến lược chứng khoán Mỹ tần số thấp sẽ rất khác với những chiến lược điều chỉnh thống kê tần số cao giao dịch trên thị trường tương lai. Trước khi lựa chọn ngôn ngữ, nhiều nhà cung cấp dữ liệu phải được đánh giá liên quan đến một chiến lược trong tay.

Nó sẽ cần thiết để xem xét kết nối với nhà cung cấp, cấu trúc của bất kỳ API, tính kịp thời của dữ liệu, yêu cầu lưu trữ và khả năng phục hồi khi một nhà cung cấp đi offline. Nó cũng là khôn ngoan để có quyền truy cập nhanh chóng đến nhiều nhà cung cấp! Các công cụ khác nhau đều có những đặc điểm lưu trữ riêng của họ, ví dụ bao gồm nhiều biểu tượng ticker cho cổ phiếu và ngày hết hạn cho hợp đồng tương lai (không kể bất kỳ dữ liệu OTC cụ thể nào). Điều này cần phải được tính vào thiết kế nền tảng.

Tần suất của chiến lược có thể là một trong những động lực lớn nhất của cách xếp chồng công nghệ sẽ được xác định.

Một chiến lược vượt quá các thanh thứ hai (tức là dữ liệu tick) dẫn đến thiết kế dựa trên hiệu suất là yêu cầu chính. Đối với các chiến lược tần số cao, một lượng lớn dữ liệu thị trường sẽ cần được lưu trữ và đánh giá. Phần mềm như HDF5 hoặc kdb + thường được sử dụng cho các vai trò này.

Để xử lý khối lượng dữ liệu rộng lớn cần thiết cho các ứng dụng HFT, phải sử dụng một hệ thống backtester và thực thi được tối ưu hóa rộng rãi. C / C ++ (có thể với một số bộ lắp ráp) có khả năng là ứng cử viên ngôn ngữ mạnh nhất.

Hệ thống nghiên cứu

Các hệ thống nghiên cứu thường liên quan đến sự pha trộn giữa phát triển tương tác và kịch bản tự động. Đầu tiên thường diễn ra trong một IDE như Visual Studio, MatLab hoặc R Studio. Sau này liên quan đến các tính toán số rộng rãi trên nhiều tham số và điểm dữ liệu. Điều này dẫn đến việc lựa chọn ngôn ngữ cung cấp một môi trường đơn giản để kiểm tra mã, nhưng cũng cung cấp hiệu suất đủ để đánh giá các chiến lược trên nhiều kích thước tham số.

Các IDE điển hình trong không gian này bao gồm Microsoft Visual C ++ / C #, chứa các tiện ích gỡ lỗi rộng rãi, khả năng hoàn thành mã (thông qua Intellisense) và tổng quan trực tiếp của toàn bộ ngăn xếp dự án (thông qua cơ sở dữ liệu ORM, LINQ); MatLab, được thiết kế cho đại số tuyến tính và các hoạt động vectorized rộng rãi, nhưng theo cách giao tiếp; R Studio, bao gồm bảng điều khiển ngôn ngữ Rstatistical trong một IDE đầy đủ; Eclipse IDE cho Java Linux và C ++; và các IDE bán sở hữu như Enthought Canopy cho Python, bao gồm các thư viện phân tích dữ liệu như NumPy, SciPy, scikit-learn và pandas trong một môi trường tương tác (console) duy nhất.

Đối với kiểm tra ngược số, tất cả các ngôn ngữ trên đều phù hợp, mặc dù không cần phải sử dụng GUI / IDE vì mã sẽ được thực thi trong nền . Việc xem xét chính ở giai đoạn này là tốc độ thực thi. Một ngôn ngữ biên dịch (như C ++) thường hữu ích nếu kích thước tham số kiểm tra ngược lớn. Hãy nhớ rằng cần phải thận trọng với các hệ thống như vậy nếu đó là trường hợp!

Các ngôn ngữ được giải thích như Python thường sử dụng các thư viện hiệu suất cao như NumPy / panda cho bước backtesting, để duy trì mức độ cạnh tranh hợp lý với các tương đương được biên dịch. Cuối cùng ngôn ngữ được chọn cho backtesting sẽ được xác định bởi nhu cầu thuật toán cụ thể cũng như phạm vi thư viện có sẵn trong ngôn ngữ (nhiều hơn về điều đó bên dưới). Tuy nhiên, ngôn ngữ được sử dụng cho backtester và môi trường nghiên cứu có thể hoàn toàn độc lập với những ngôn ngữ được sử dụng trong danh mục xây dựng, quản lý rủi ro và các thành phần thực thi, như sẽ được thấy.

Xây dựng danh mục đầu tư và quản lý rủi ro

Các thành phần xây dựng danh mục đầu tư và quản lý rủi ro thường bị bỏ qua bởi các nhà giao dịch thuật toán bán lẻ. Điều này gần như luôn luôn là một sai lầm. Những công cụ này cung cấp cơ chế mà qua đó vốn sẽ được bảo tồn.

Các phiên bản phức tạp của các thành phần này có thể có tác động đáng kể đến chất lượng và tính nhất quán của lợi nhuận. Thật đơn giản để tạo ra một chiến lược ổn định vì cơ chế xây dựng danh mục đầu tư và quản lý rủi ro có thể dễ dàng được sửa đổi để xử lý nhiều hệ thống. Do đó, chúng nên được coi là các thành phần thiết yếu ngay từ đầu khi thiết kế một hệ thống giao dịch thuật toán.

Công việc của hệ thống xây dựng danh mục đầu tư là lấy một tập hợp các giao dịch mong muốn và tạo ra tập hợp các giao dịch thực tế giúp giảm thiểu sự giảm thiểu, duy trì các rủi ro đối với các yếu tố khác nhau (như các lĩnh vực, lớp tài sản, biến động vv) và tối ưu hóa việc phân bổ vốn cho các chiến lược khác nhau trong danh mục đầu tư.

Việc xây dựng danh mục đầu tư thường giảm xuống một vấn đề đại số tuyến tính (như phân tử ma trận) và do đó hiệu suất phụ thuộc rất nhiều vào hiệu quả của việc thực hiện đại số tuyến tính số có sẵn. Các thư viện phổ biến bao gồm uBLAS, LAPACK và NAG cho C ++. MatLab cũng sở hữu các hoạt động ma trận được tối ưu hóa rộng rãi. Python sử dụng NumPy / SciPy cho các tính toán như vậy. Một danh mục đầu tư thường xuyên cân bằng lại sẽ yêu cầu một thư viện ma trận được biên dịch (và tối ưu hóa tốt!) để thực hiện bước này, để không gây tắc nghẽn cho hệ thống giao dịch.

Quản lý rủi ro là một phần cực kỳ quan trọng khác của một hệ thống giao dịch thuật toán. Rủi ro có thể có nhiều hình thức: Tăng biến động (mặc dù điều này có thể được xem là mong muốn cho một số chiến lược nhất định!), Tăng mối tương quan giữa các lớp tài sản, mặc định đối tác, ngưng hoạt động máy chủ, các sự kiện black swan và các lỗi không được phát hiện trong mã giao dịch, để nêu một vài trường hợp.

Các thành phần quản lý rủi ro cố gắng dự đoán tác động của sự biến động quá mức và mối tương quan giữa các lớp tài sản và tác động tiếp theo của chúng đối với vốn giao dịch. Thông thường điều này giảm xuống một tập hợp các tính toán thống kê như Monte Carlo kiểm tra căng thẳng. Điều này rất giống với nhu cầu tính toán của một công cụ định giá phái sinh và như vậy sẽ bị ràng buộc bởi CPU.

Hệ thống thi hành

Công việc của hệ thống thực thi là nhận tín hiệu giao dịch được lọc từ các thành phần xây dựng danh mục đầu tư và quản lý rủi ro và gửi chúng đến môi giới hoặc các phương tiện tiếp cận thị trường khác. Đối với phần lớn các chiến lược giao dịch thuật toán bán lẻ, điều này liên quan đến kết nối API hoặc FIX với môi giới như Interactive Brokers. Những cân nhắc chính khi quyết định một ngôn ngữ bao gồm chất lượng của API, khả năng gói ngôn ngữ cho API, tần suất thực thi và trượt dự kiến.

chất lượng của API đề cập đến việc nó được tài liệu tốt như thế nào, loại hiệu suất mà nó cung cấp, cho dù nó cần phần mềm độc lập để truy cập hay không có cổng có thể được thiết lập theo cách không có đầu (tức là không có GUI). Trong trường hợp của Interactive Brokers, công cụ Trader WorkStation cần phải chạy trong môi trường GUI để truy cập API của họ. Tôi đã từng phải cài đặt phiên bản Ubuntu Desktop trên máy chủ đám mây Amazon để truy cập Interactive Brokers từ xa, chỉ vì lý do này!

Hầu hết các API sẽ cung cấp một giao diện C ++ và / hoặc Java. Thông thường là cộng đồng phát triển các gói cụ thể cho ngôn ngữ cho C #, Python, R, Excel và MatLab. Lưu ý rằng với mỗi plugin bổ sung được sử dụng (đặc biệt là các gói API) có phạm vi cho các lỗi lẻn vào hệ thống. Luôn luôn kiểm tra các plugin của loại này và đảm bảo chúng được duy trì tích cực. Một thước đo có giá trị là xem có bao nhiêu bản cập nhật mới cho một cơ sở mã đã được thực hiện trong những tháng gần đây.

Tần suất thực thi là rất quan trọng trong thuật toán thực thi. Lưu ý rằng hàng trăm lệnh có thể được gửi mỗi phút và như vậy hiệu suất là rất quan trọng.

Các ngôn ngữ kiểu tĩnh (xem bên dưới) như C ++ / Java nói chung là tối ưu cho việc thực hiện nhưng có sự đánh đổi về thời gian phát triển, kiểm tra và dễ bảo trì. Các ngôn ngữ kiểu động, như Python và Perl hiện nay nói chung là đủ nhanh. Luôn đảm bảo các thành phần được thiết kế theo cách mô-đun (xem bên dưới) để chúng có thể được thay thế khi hệ thống mở rộng.

Quá trình lập kế hoạch và phát triển kiến trúc

Các thành phần của một hệ thống giao dịch, yêu cầu về tần suất và khối lượng của nó đã được thảo luận ở trên, nhưng cơ sở hạ tầng hệ thống vẫn chưa được đề cập. Những người hoạt động như một nhà giao dịch bán lẻ hoặc làm việc trong một quỹ nhỏ có thể sẽ "bắt nhiều mũ".

Sự tách biệt những lo lắng

Một trong những quyết định quan trọng nhất phải được thực hiện ngay từ đầu là làm thế nào để tách các mối quan tâm của một hệ thống giao dịch.

Bằng cách phơi bày các giao diện tại mỗi thành phần, dễ dàng thay thế các phần của hệ thống cho các phiên bản khác hỗ trợ hiệu suất, độ tin cậy hoặc bảo trì, mà không cần sửa đổi bất kỳ mã phụ thuộc bên ngoài nào. Đây là "thực hành tốt nhất" cho các hệ thống như vậy. Đối với các chiến lược ở tần số thấp hơn, các thực hành như vậy được khuyến cáo. Đối với giao dịch tần số cực cao, sổ quy tắc có thể phải bị bỏ qua với chi phí điều chỉnh hệ thống để có hiệu suất cao hơn. Một hệ thống kết nối chặt chẽ hơn có thể là mong muốn.

Tạo ra một bản đồ thành phần của một hệ thống giao dịch thuật toán có giá trị một bài viết trong chính nó. Tuy nhiên, một cách tiếp cận tối ưu là đảm bảo có các thành phần riêng biệt cho các đầu vào dữ liệu thị trường lịch sử và thời gian thực, lưu trữ dữ liệu, API truy cập dữ liệu, backtester, tham số chiến lược, xây dựng danh mục đầu tư, quản lý rủi ro và các hệ thống thực thi tự động.

Ví dụ, nếu kho dữ liệu đang được sử dụng hiện đang hoạt động kém hơn, ngay cả ở mức tối ưu hóa đáng kể, nó có thể được thay thế bằng cách viết lại tối thiểu vào API nhập dữ liệu hoặc truy cập dữ liệu.

Một lợi ích khác của các thành phần tách biệt là nó cho phép sử dụng nhiều ngôn ngữ lập trình trong hệ thống tổng thể. Không cần phải bị giới hạn trong một ngôn ngữ duy nhất nếu phương pháp giao tiếp của các thành phần là độc lập ngôn ngữ. Điều này sẽ xảy ra nếu chúng giao tiếp qua TCP / IP, ZeroMQ hoặc một số giao thức độc lập ngôn ngữ khác.

Như một ví dụ cụ thể, hãy xem xét trường hợp một hệ thống backtesting được viết bằng C ++ cho hiệu suất number crunching, trong khi quản lý danh mục đầu tư và các hệ thống thực thi được viết bằng Python bằng cách sử dụng SciPy và IBPy.

Các cân nhắc về hiệu suất

Hiệu suất là một yếu tố quan trọng đối với hầu hết các chiến lược giao dịch. Đối với các chiến lược tần số cao hơn, nó là yếu tố quan trọng nhất. Hiệu suất bao gồm một loạt các vấn đề, chẳng hạn như tốc độ thực thi thuật toán, độ trễ mạng, băng thông, I / O dữ liệu, đồng thời / song song và mở rộng quy mô. Mỗi lĩnh vực này được đề cập riêng bởi các sách giáo khoa lớn, vì vậy bài viết này sẽ chỉ xé bề mặt của mỗi chủ đề. Kiến trúc và lựa chọn ngôn ngữ sẽ được thảo luận về tác động của chúng đến hiệu suất.

Theo Donald Knuth, một trong những người cha của Khoa học Máy tính, "tối ưu hóa sớm là gốc rễ của mọi sự xấu xa". Điều này hầu như luôn luôn đúng - ngoại trừ khi xây dựng một thuật toán giao dịch tần số cao! Đối với những người quan tâm đến các chiến lược tần số thấp hơn, một cách tiếp cận phổ biến là xây dựng một hệ thống theo cách đơn giản nhất có thể và chỉ tối ưu hóa khi các nút thắt bắt đầu xuất hiện.

Các công cụ lập hồ sơ được sử dụng để xác định nơi xảy ra các nút thắt. Các hồ sơ có thể được tạo cho tất cả các yếu tố được liệt kê ở trên, trong môi trường MS Windows hoặc Linux. Có nhiều hệ điều hành và các công cụ ngôn ngữ có sẵn để làm như vậy, cũng như các tiện ích của bên thứ ba. Việc lựa chọn ngôn ngữ sẽ được thảo luận trong bối cảnh hiệu suất.

C++, Java, Python, R và MatLab đều chứa các thư viện hiệu suất cao (hoặc là một phần của tiêu chuẩn hoặc bên ngoài) cho cấu trúc dữ liệu cơ bản và công việc thuật toán. C++ đi kèm với Thư viện mẫu tiêu chuẩn, trong khi Python chứa NumPy / SciPy. Các nhiệm vụ toán học phổ biến được tìm thấy trong các thư viện này và hiếm khi có lợi khi viết một triển khai mới.

Một ngoại lệ là nếu kiến trúc phần cứng được tùy chỉnh cao là cần thiết và một thuật toán đang sử dụng rộng rãi các tiện ích mở rộng độc quyền (như bộ nhớ cache tùy chỉnh). Tuy nhiên, thường tái phát minh bánh xe lãng phí thời gian có thể được sử dụng tốt hơn để phát triển và tối ưu hóa các phần khác của cơ sở hạ tầng giao dịch. Thời gian phát triển là cực kỳ quý giá đặc biệt là trong bối cảnh của các nhà phát triển duy nhất.

Độ trễ thường là vấn đề của hệ thống thực thi vì các công cụ nghiên cứu thường nằm trên cùng một máy. Đối với các công cụ đầu tiên, độ trễ có thể xảy ra ở nhiều điểm dọc theo đường thực thi. Các cơ sở dữ liệu phải được truy vấn (trọng lượng đĩa / mạng), các tín hiệu phải được tạo ra (hệ điều hành, trọng lượng nhắn tin lõi), các tín hiệu giao dịch được gửi (trọng lượng NIC) và các đơn đặt hàng được xử lý (trọng lượng trọng lượng nội bộ hệ thống trao đổi).

Đối với các hoạt động tần số cao hơn, cần phải trở nên quen thuộc với tối ưu hóa lõi cũng như tối ưu hóa truyền tải mạng. Đây là một lĩnh vực sâu và vượt xa phạm vi của bài viết nhưng nếu một thuật toán UHFT được mong muốn thì hãy nhận thức được chiều sâu kiến thức cần thiết!

Caching rất hữu ích trong bộ công cụ của một nhà phát triển giao dịch định lượng. Caching đề cập đến khái niệm lưu trữ dữ liệu được truy cập thường xuyên theo cách cho phép truy cập hiệu suất cao hơn, bằng cách chi tiêu khả năng không hoạt động của dữ liệu. Một trường hợp sử dụng phổ biến xảy ra trong phát triển web khi lấy dữ liệu từ cơ sở dữ liệu quan hệ được hỗ trợ bằng đĩa và đưa nó vào bộ nhớ. Bất kỳ yêu cầu tiếp theo nào về dữ liệu không phải "đánh vào cơ sở dữ liệu" và do đó lợi ích hiệu suất có thể đáng kể.

Đối với các tình huống giao dịch, bộ nhớ cache có thể cực kỳ có lợi. Ví dụ, trạng thái hiện tại của danh mục đầu tư chiến lược có thể được lưu trữ trong bộ nhớ cache cho đến khi nó được cân bằng lại, do đó danh sách không cần phải được tái tạo trên mỗi vòng lặp của thuật toán giao dịch.

Tuy nhiên, lưu trữ bộ nhớ cache không phải là không có vấn đề của riêng mình. Tái tạo dữ liệu bộ nhớ cache tất cả cùng một lúc, do bản chất dễ bay hơi của lưu trữ bộ nhớ cache, có thể đặt nhu cầu đáng kể đối với cơ sở hạ tầng. Một vấn đề khác là đống chó, trong đó nhiều thế hệ của một bản sao bộ nhớ cache mới được thực hiện dưới tải trọng cực kỳ cao, dẫn đến thất bại thác.

Việc phân bổ bộ nhớ động là một hoạt động tốn kém trong việc thực hiện phần mềm. Do đó, điều bắt buộc đối với các ứng dụng giao dịch hiệu suất cao hơn là phải nhận thức rõ về cách bộ nhớ được phân bổ và phân bổ trong quá trình luồng chương trình. Các tiêu chuẩn ngôn ngữ mới hơn như Java, C # và Python đều thực hiện thu gom rác tự động, đề cập đến việc phân bổ bộ nhớ phân bổ năng động khi các đối tượng đi ra khỏi phạm vi.

Thu thập rác là cực kỳ hữu ích trong quá trình phát triển vì nó làm giảm lỗi và hỗ trợ khả năng đọc. Tuy nhiên, nó thường không tối ưu cho một số chiến lược giao dịch tần số cao nhất định. Thu thập rác tùy chỉnh thường được mong muốn cho những trường hợp này. Ví dụ, trong Java, bằng cách điều chỉnh bộ thu thập rác và cấu hình chồng, có thể đạt được hiệu suất cao cho các chiến lược HFT.

C++ không cung cấp bộ thu rác gốc và do đó cần phải xử lý tất cả việc phân bổ / phân bổ bộ nhớ như là một phần của việc thực hiện đối tượng. Mặc dù có khả năng mắc lỗi (có khả năng dẫn đến các con trỏ treo) nhưng điều cực kỳ hữu ích là có thể kiểm soát chi tiết cách các đối tượng xuất hiện trên đống cho một số ứng dụng nhất định. Khi chọn ngôn ngữ, hãy chắc chắn nghiên cứu cách bộ thu rác hoạt động và liệu nó có thể được sửa đổi để tối ưu hóa cho một trường hợp sử dụng cụ thể.

Nhiều hoạt động trong các hệ thống giao dịch thuật toán có khả năng song song. Điều này đề cập đến khái niệm thực hiện nhiều hoạt động lập trình cùng một lúc, tức là song song. Những thuật toán được gọi là song song khó tính bao gồm các bước có thể được tính toán hoàn toàn độc lập với các bước khác. Một số hoạt động thống kê nhất định, chẳng hạn như mô phỏng Monte Carlo, là một ví dụ tốt về các thuật toán song song khó khăn vì mỗi phép rút lượn ngẫu nhiên và hoạt động đường dẫn tiếp theo có thể được tính toán mà không cần kiến thức về các đường dẫn khác.

Các thuật toán khác chỉ có thể song song một phần. Mô phỏng động lực học chất lỏng là một ví dụ như vậy, nơi mà lĩnh vực tính toán có thể được chia nhỏ, nhưng cuối cùng các lĩnh vực này phải giao tiếp với nhau và do đó các hoạt động là một phần liên tục. Các thuật toán song song phải tuân theo Luật Amdahl, cung cấp một giới hạn trên lý thuyết cho việc tăng hiệu suất của một thuật toán song song khi phải chịu các quy trình riêng biệt NN (ví dụ: trên một lõi CPU hoặc thread).

Tương tự hóa ngày càng trở nên quan trọng như một phương tiện tối ưu hóa kể từ khi tốc độ đồng hồ của bộ vi xử lý bị trì trệ, vì các bộ vi xử lý mới hơn chứa nhiều lõi để thực hiện tính toán song song. Sự gia tăng của phần cứng đồ họa tiêu dùng (chủ yếu cho trò chơi điện tử) đã dẫn đến sự phát triển của Đơn vị xử lý đồ họa (GPU), có chứa hàng trăm lõi cho các hoạt động đồng thời cao.

Phần cứng GPU như vậy thường chỉ phù hợp với khía cạnh nghiên cứu tài chính định lượng, trong khi các phần cứng chuyên biệt hơn khác (bao gồm cả Field-Programmable Gate Arrays - FPGA) được sử dụng cho (U) HFT. Ngày nay, hầu hết các ngôn ngữ hiện đại đều hỗ trợ một mức độ đồng thời / đa luồng. Do đó, việc tối ưu hóa một backtester là đơn giản, vì tất cả các tính toán thường độc lập với những người khác.

Kích thước trong kỹ thuật phần mềm và hoạt động đề cập đến khả năng của hệ thống để xử lý tải tăng liên tục dưới dạng các yêu cầu lớn hơn, sử dụng bộ xử lý cao hơn và phân bổ bộ nhớ nhiều hơn. Trong giao dịch thuật toán, một chiến lược có thể mở rộng quy mô nếu nó có thể chấp nhận số lượng vốn lớn hơn và vẫn tạo ra lợi nhuận nhất quán.

Trong khi các hệ thống phải được thiết kế để mở rộng quy mô, thường khó dự đoán trước khi xảy ra nút thắt. Việc ghi chép, thử nghiệm, lập hồ sơ và giám sát nghiêm ngặt sẽ giúp ích rất nhiều trong việc cho phép một hệ thống mở rộng quy mô. Các ngôn ngữ tự nó thường được mô tả là không có khả năng mở rộng quy mô. Điều này thường là kết quả của thông tin sai lệch, chứ không phải là sự thật.

Một phương tiện quản lý quy mô là tách các mối quan tâm, như đã đề cập ở trên. Để tiếp tục giới thiệu khả năng xử lý spikes trong hệ thống (tức là biến động đột ngột gây ra một loạt các giao dịch), nó hữu ích để tạo ra một kiến trúc message queuing. Điều này đơn giản có nghĩa là đặt một hệ thống hàng đợi tin nhắn giữa các thành phần để các đơn đặt hàng được đặt chồng lên nếu một thành phần nhất định không thể xử lý nhiều yêu cầu.

Thay vì yêu cầu bị mất, chúng chỉ đơn giản được giữ trong một ngăn xếp cho đến khi thông điệp được xử lý. Điều này đặc biệt hữu ích khi gửi giao dịch đến một công cụ thực thi. Nếu công cụ bị trễ nặng thì nó sẽ sao lưu giao dịch. Một hàng đợi giữa máy tạo tín hiệu giao dịch và API thực thi sẽ giảm thiểu vấn đề này với chi phí trượt thương mại tiềm năng. Một nhà môi giới hàng đợi thông điệp nguồn mở được tôn trọng là RabbitMQ.

Phần cứng và hệ điều hành

Phần cứng chạy chiến lược của bạn có thể có tác động đáng kể đến lợi nhuận của thuật toán của bạn. Đây cũng không phải là vấn đề giới hạn ở các nhà giao dịch tần số cao. Sự lựa chọn kém về phần cứng và hệ điều hành có thể dẫn đến sự cố máy hoặc khởi động lại vào thời điểm không phù hợp nhất. Do đó, cần phải xem xét nơi ứng dụng của bạn sẽ ở. Sự lựa chọn thường là giữa máy tính để bàn cá nhân, máy chủ từ xa, nhà cung cấp cloud hoặc máy chủ đồng vị trí trao đổi.

Máy tính để bàn rất đơn giản để cài đặt và quản lý, đặc biệt là với các hệ điều hành thân thiện với người dùng mới hơn như Windows 7/8, Mac OSX và Ubuntu. Tuy nhiên, các hệ điều hành để bàn có một số nhược điểm đáng kể.

Sử dụng phần cứng trong môi trường nhà (hoặc văn phòng địa phương) có thể dẫn đến các vấn đề về kết nối internet và thời gian hoạt động điện. Lợi ích chính của một hệ thống máy tính để bàn là sức mạnh tính toán đáng kể có thể được mua với một phần chi phí của một máy chủ chuyên dụng từ xa (hoặc hệ thống dựa trên đám mây) có tốc độ tương đương.

Một máy chủ chuyên dụng hoặc máy tính dựa trên đám mây, mặc dù thường đắt hơn tùy chọn máy tính để bàn, cho phép cơ sở hạ tầng dư thừa đáng kể hơn, chẳng hạn như sao lưu dữ liệu tự động, khả năng đảm bảo thời gian hoạt động và giám sát từ xa một cách đơn giản hơn. Chúng khó quản lý hơn vì chúng đòi hỏi khả năng sử dụng khả năng đăng nhập từ xa của hệ điều hành.

Trong Windows, điều này thường thông qua GUI Remote Desktop Protocol (RDP). Trong các hệ thống dựa trên Unix, dòng lệnh Secure SHell (SSH) được sử dụng. Cơ sở hạ tầng máy chủ dựa trên Unix hầu như luôn dựa trên dòng lệnh, ngay lập tức làm cho các công cụ lập trình dựa trên GUI (như MatLab hoặc Excel) không thể sử dụng được.

Một máy chủ đồng vị trí, như cụm từ được sử dụng trong thị trường vốn, chỉ đơn giản là một máy chủ chuyên dụng nằm trong một sàn giao dịch để giảm độ trễ của thuật toán giao dịch.

Các khía cạnh cuối cùng để lựa chọn phần cứng và lựa chọn ngôn ngữ lập trình là nền tảng độc lập. Có cần thiết cho mã để chạy trên nhiều hệ điều hành khác nhau? Có phải mã được thiết kế để chạy trên một loại kiến trúc bộ xử lý cụ thể, chẳng hạn như Intel x86/x64 hoặc có thể thực hiện trên các bộ xử lý RISC như các bộ xử lý được sản xuất bởi ARM? Những vấn đề này sẽ phụ thuộc rất nhiều vào tần suất và loại chiến lược được thực hiện.

Khả năng phục hồi và thử nghiệm

Một trong những cách tốt nhất để mất rất nhiều tiền trên giao dịch thuật toán là tạo ra một hệ thống không có khả năng phục hồi. Điều này đề cập đến độ bền của hệ thống khi chịu các sự kiện hiếm hoi, chẳng hạn như phá sản môi giới, biến động quá mức đột ngột, thời gian ngừng hoạt động trên toàn khu vực cho nhà cung cấp máy chủ đám mây hoặc xóa vô tình toàn bộ cơ sở dữ liệu giao dịch. Nhiều năm lợi nhuận có thể bị loại bỏ trong vòng vài giây với kiến trúc được thiết kế kém.

Có khả năng rằng trong bất kỳ ứng dụng giao dịch định lượng tùy chỉnh hợp lý phức tạp nào, ít nhất 50% thời gian phát triển sẽ được dành cho việc gỡ lỗi, thử nghiệm và bảo trì.

Hầu như tất cả các ngôn ngữ lập trình đều đi kèm với một trình gỡ lỗi liên quan hoặc có các giải pháp thay thế của bên thứ ba được tôn trọng. Về cơ bản, một trình gỡ lỗi cho phép thực thi một chương trình bằng cách chèn các điểm ngắt tùy ý trong đường dẫn mã, tạm dừng thực thi để điều tra trạng thái của hệ thống. Lợi ích chính của việc gỡ lỗi là có thể điều tra hành vi của mã trước một điểm bị hỏng được biết.

Debugging là một thành phần thiết yếu trong hộp công cụ để phân tích lỗi lập trình. Tuy nhiên, chúng được sử dụng rộng rãi hơn trong các ngôn ngữ được biên dịch như C ++ hoặc Java, vì các ngôn ngữ được giải thích như Python thường dễ gỡ lỗi hơn do ít LOC và ít câu nói hơn. Mặc dù xu hướng này, Python vẫn đi kèm với pdb, một công cụ gỡ lỗi tinh vi.

Kiểm tra trong phát triển phần mềm đề cập đến quá trình áp dụng các tham số và kết quả được biết đến cho các chức năng, phương pháp và đối tượng cụ thể trong cơ sở mã, để mô phỏng hành vi và đánh giá nhiều đường dẫn mã, giúp đảm bảo rằng một hệ thống hoạt động đúng cách. Một mô hình mới hơn được gọi là Phát triển dựa trên thử nghiệm (TDD), trong đó mã thử nghiệm được phát triển chống lại một giao diện được chỉ định mà không có việc thực hiện. Trước khi hoàn thành cơ sở mã thực tế, tất cả các thử nghiệm sẽ thất bại. Khi mã được viết để "lấp đầy chỗ trống", tất cả các thử nghiệm cuối cùng sẽ vượt qua, tại thời điểm đó phát triển nên ngừng.

TDD đòi hỏi thiết kế thông số kỹ thuật mở rộng trước cũng như mức độ kỷ luật lành mạnh để thực hiện thành công. Trong C ++, Boost cung cấp một khuôn khổ kiểm tra đơn vị. Trong Java, thư viện JUnit tồn tại để thực hiện cùng một mục đích. Python cũng có mô-đun unittest như một phần của thư viện tiêu chuẩn. Nhiều ngôn ngữ khác có khuôn khổ kiểm tra đơn vị và thường có nhiều tùy chọn.

Trong môi trường sản xuất, ghi chép phức tạp là hoàn toàn cần thiết. ghi chép là quá trình xuất thông điệp, với mức độ nghiêm trọng khác nhau, liên quan đến hành vi thực thi của một hệ thống đến một tệp phẳng hoặc cơ sở dữ liệu. ghi chép là một "lực tấn công đầu tiên" khi săn lùng hành vi chạy chương trình bất ngờ.

Cả Microsoft Windows và Linux đều đi kèm với khả năng ghi nhật ký hệ thống rộng rãi và các ngôn ngữ lập trình có xu hướng đi kèm với các thư viện ghi nhật ký tiêu chuẩn bao gồm hầu hết các trường hợp sử dụng.

Trong khi ghi nhật ký của một hệ thống sẽ cung cấp thông tin về những gì đã xảy ra trong quá khứ, việc theo dõi một ứng dụng sẽ cung cấp cái nhìn sâu sắc về những gì đang xảy ra ngay bây giờ. Tất cả các khía cạnh của hệ thống nên được xem xét để theo dõi. Các số liệu cấp hệ thống như sử dụng đĩa, bộ nhớ có sẵn, băng thông mạng và sử dụng CPU cung cấp thông tin tải cơ bản.

Các chỉ số giao dịch như giá/thế lượng bất thường, rút tiền đột ngột và nhanh chóng và tiếp xúc tài khoản cho các lĩnh vực/thị trường khác nhau cũng nên được theo dõi liên tục.

Giám sát hệ thống thường là lĩnh vực của người quản lý hệ thống hoặc người quản lý hoạt động. Tuy nhiên, với tư cách là một nhà phát triển giao dịch duy nhất, các số liệu này phải được thiết lập như một phần của thiết kế lớn hơn. Có nhiều giải pháp để giám sát: độc quyền, lưu trữ và nguồn mở, cho phép tùy chỉnh rộng rãi các số liệu cho một trường hợp sử dụng cụ thể.

Các bản sao lưu và tính sẵn có cao nên là mối quan tâm chính của một hệ thống giao dịch. Hãy xem xét hai câu hỏi sau đây: 1) Nếu một cơ sở dữ liệu sản xuất toàn bộ dữ liệu thị trường và lịch sử giao dịch bị xóa (không có bản sao lưu), thuật toán nghiên cứu và thực thi sẽ bị ảnh hưởng như thế nào? 2) Nếu hệ thống giao dịch bị gián đoạn trong một thời gian dài (với các vị trí mở), tài khoản và lợi nhuận liên tục sẽ bị ảnh hưởng như thế nào?

Điều bắt buộc là phải thiết lập một hệ thống sao lưu dữ liệu và cũng để kiểm tra việc khôi phục dữ liệu đó. Nhiều cá nhân không kiểm tra một chiến lược khôi phục. Nếu việc khôi phục sau một vụ tai nạn không được thử nghiệm trong một môi trường an toàn, đảm bảo nào có thể có được việc khôi phục vào thời điểm tồi tệ nhất có thể?

Tương tự như vậy, khả năng sẵn có cao cần phải được n trong ngay từ đầu. Cơ sở hạ tầng dư thừa (ngay cả với chi phí bổ sung) luôn phải được xem xét, vì chi phí thời gian ngừng hoạt động có thể vượt xa chi phí bảo trì liên tục của các hệ thống như vậy. Tôi sẽ không đi sâu vào chủ đề này vì nó là một khu vực lớn, nhưng hãy chắc chắn rằng nó là một trong những cân nhắc đầu tiên được đưa ra cho hệ thống giao dịch của bạn.

Chọn ngôn ngữ

Bây giờ đã được cung cấp chi tiết đáng kể về các yếu tố khác nhau phát sinh khi phát triển một hệ thống giao dịch thuật toán hiệu suất cao tùy chỉnh.

Hệ thống kiểu

Khi lựa chọn một ngôn ngữ cho một ngăn xếp giao dịch, cần phải xem xét hệ thống kiểu. Các ngôn ngữ có lợi cho giao dịch thuật toán là kiểu tĩnh hoặc kiểu động. Một ngôn ngữ kiểu tĩnh thực hiện kiểm tra các loại (ví dụ như số nguyên, phơi, lớp tùy chỉnh vv) trong quá trình biên dịch. Những ngôn ngữ như C ++ và Java. Một ngôn ngữ kiểu động thực hiện phần lớn việc kiểm tra kiểu của nó tại thời điểm chạy. Những ngôn ngữ như Python, Perl và JavaScript.

Đối với một hệ thống số cao như một công cụ giao dịch thuật toán, kiểm tra kiểu tại thời điểm biên dịch có thể cực kỳ có lợi, vì nó có thể loại bỏ nhiều lỗi mà nếu không sẽ dẫn đến lỗi số. Tuy nhiên, kiểm tra kiểu không bắt được tất cả mọi thứ, và đây là nơi xử lý ngoại lệ xuất hiện do sự cần thiết phải xử lý các hoạt động bất ngờ.

Một lợi ích khác của các ngôn ngữ kiểu tĩnh là trình biên dịch có thể thực hiện nhiều tối ưu hóa mà không có sẵn cho ngôn ngữ kiểu động, đơn giản vì kiểu (và do đó yêu cầu bộ nhớ) được biết tại thời điểm biên dịch.

Mã nguồn mở hay độc quyền?

Một trong những lựa chọn lớn nhất có sẵn cho một nhà phát triển giao dịch thuật toán là sử dụng các công nghệ độc quyền (thương mại) hoặc nguồn mở. Có những lợi thế và nhược điểm cho cả hai cách tiếp cận.

Microsoft.NET stack (bao gồm Visual C ++, Visual C #) và MathWorks MatLab là hai trong số các lựa chọn độc quyền lớn hơn để phát triển phần mềm giao dịch thuật toán tùy chỉnh.

Microsoft và MathWorks đều cung cấp tài liệu chất lượng cao cho các sản phẩm của họ. Hơn nữa, các cộng đồng xung quanh mỗi công cụ rất lớn với các diễn đàn web hoạt động cho cả hai. Phần mềm.NET cho phép tích hợp chặt chẽ với nhiều ngôn ngữ như C ++, C # và VB, cũng như liên kết dễ dàng với các sản phẩm khác của Microsoft như cơ sở dữ liệu SQL Server thông qua LINQ. MatLab cũng có nhiều plugin / thư viện (một số miễn phí, một số thương mại) cho hầu hết các lĩnh vực nghiên cứu định lượng.

Ngoài ra còn có những nhược điểm. Với bất kỳ phần mềm nào, chi phí không phải là không đáng kể đối với một nhà kinh doanh đơn độc (mặc dù Microsoft cung cấp phiên bản nhập cảnh của Visual Studio miễn phí). Các công cụ của Microsoft chơi tốt với nhau, nhưng tích hợp kém hơn với mã bên ngoài. Visual Studio cũng phải được thực hiện trên Microsoft Windows, có thể cho rằng hiệu suất thấp hơn nhiều so với máy chủ Linux tương đương được điều chỉnh tối ưu.

MatLab cũng thiếu một vài plugin chính như một gói tốt xung quanh API Interactive Brokers, một trong số ít các nhà môi giới có khả năng giao dịch thuật toán hiệu suất cao. Vấn đề chính với các sản phẩm độc quyền là thiếu sẵn có mã nguồn. Điều này có nghĩa là nếu thực sự yêu cầu hiệu suất cực cao, cả hai công cụ này sẽ ít hấp dẫn hơn nhiều.

Các công cụ nguồn mở đã được công nghiệp cấp từ một thời gian. Phần lớn không gian tài sản thay thế sử dụng rộng rãi nguồn mở Linux, MySQL / PostgreSQL, Python, R, C ++ và Java trong các vai trò sản xuất hiệu suất cao. Tuy nhiên, chúng không giới hạn trong lĩnh vực này. Python và R, đặc biệt, chứa rất nhiều thư viện số rộng rãi để thực hiện gần như bất kỳ loại phân tích dữ liệu nào có thể tưởng tượng được, thường ở tốc độ thực thi tương đương với các ngôn ngữ biên dịch, với một số cảnh báo nhất định.

Lợi ích chính của việc sử dụng các ngôn ngữ được giải thích là tốc độ phát triển. Python và R đòi hỏi ít dòng mã hơn để đạt được chức năng tương tự, chủ yếu là do các thư viện rộng lớn. Hơn nữa, chúng thường cho phép phát triển dựa trên console tương tác, nhanh chóng giảm quá trình phát triển lặp đi lặp lại.

Với thời gian là một nhà phát triển cực kỳ có giá trị, và tốc độ thực thi thường ít hơn (trừ khi trong không gian HFT), nó là đáng để xem xét rộng rãi để một công nghệ nguồn mở ngăn xếp. Python và R sở hữu cộng đồng phát triển đáng kể và được hỗ trợ cực kỳ tốt, do sự phổ biến của họ. Tài liệu là tuyệt vời và lỗi (ít nhất là cho thư viện cốt lõi) vẫn còn khan hiếm.

Các công cụ nguồn mở thường bị thiếu hợp đồng hỗ trợ thương mại chuyên dụng và chạy tối ưu trên các hệ thống có giao diện người dùng ít tha thứ hơn. Một máy chủ Linux điển hình (như Ubuntu) thường sẽ hoàn toàn hướng dòng lệnh. Ngoài ra, Python và R có thể chậm cho một số nhiệm vụ thực thi. Có các cơ chế tích hợp với C ++ để cải thiện tốc độ thực thi, nhưng nó đòi hỏi một số kinh nghiệm trong lập trình đa ngôn ngữ.

Mặc dù phần mềm độc quyền không miễn nhiễm với các vấn đề phụ thuộc / phiên bản, nhưng việc phải đối phó với các phiên bản thư viện không chính xác trong môi trường như vậy ít phổ biến hơn nhiều.

Tôi sẽ mạo hiểm ý kiến cá nhân của mình ở đây và tuyên bố rằng tôi xây dựng tất cả các công cụ giao dịch của mình với các công nghệ nguồn mở. Đặc biệt tôi sử dụng: Ubuntu, MySQL, Python, C ++ và R. Sự trưởng thành, quy mô cộng đồng, khả năng đào sâu nếu vấn đề xảy ra và giảm tổng chi phí sở hữu (TCO) vượt xa sự đơn giản của các GUI độc quyền và cài đặt dễ dàng hơn.

Bao gồm pin?

Tiêu đề của phần này đề cập đến khả năng out of the box của ngôn ngữ - nó chứa những thư viện nào và chúng tốt như thế nào? Đây là nơi các ngôn ngữ trưởng thành có lợi thế so với các biến thể mới hơn.

C++ nổi tiếng với thư viện mẫu tiêu chuẩn (STL) chứa rất nhiều cấu trúc dữ liệu hiệu suất cao và thuật toán miễn phí. Python được biết đến với khả năng giao tiếp với hầu hết các loại hệ thống / giao thức khác (đặc biệt là web), chủ yếu thông qua thư viện tiêu chuẩn của riêng nó. R có rất nhiều công cụ thống kê và kinh tế học tích hợp, trong khi MatLab được tối ưu hóa cho bất kỳ mã đại số tuyến tính số nào (có thể được tìm thấy trong tối ưu hóa danh mục đầu tư và định giá phái sinh, ví dụ).

Bên ngoài các thư viện tiêu chuẩn, C++ sử dụng thư viện Boost, lấp đầy các phần bị thiếu của thư viện tiêu chuẩn.

Python có sự kết hợp thư viện phân tích dữ liệu hiệu suất cao NumPy / SciPy / Panda, được chấp nhận rộng rãi cho nghiên cứu giao dịch thuật toán. Hơn nữa, các plugin hiệu suất cao tồn tại để truy cập các cơ sở dữ liệu quan hệ chính, chẳng hạn như MySQL ++ (MySQL / C ++), JDBC (Java / MatLab), MySQLdb (MySQL / Python) và psychopg2 (PostgreSQL / Python). Python thậm chí có thể giao tiếp với R thông qua plugin RPy!

Một khía cạnh thường bị bỏ qua của một hệ thống giao dịch trong khi ở giai đoạn nghiên cứu và thiết kế ban đầu là kết nối với một API môi giới. Hầu hết các API hỗ trợ C ++ và Java, nhưng một số cũng hỗ trợ C # và Python, trực tiếp hoặc với mã bọc do cộng đồng cung cấp cho các API C ++. Đặc biệt, các nhà môi giới tương tác có thể được kết nối qua plugin IBPy. Nếu cần hiệu suất cao, các công ty môi giới sẽ hỗ trợ giao thức FIX.

Kết luận

Như hiện nay rõ ràng, việc lựa chọn ngôn ngữ lập trình cho một hệ thống giao dịch thuật toán không đơn giản và đòi hỏi phải suy nghĩ sâu sắc. Các cân nhắc chính là hiệu suất, dễ phát triển, khả năng phục hồi và thử nghiệm, tách các mối quan tâm, quen thuộc, bảo trì, tính sẵn có mã nguồn, chi phí cấp phép và độ trưởng thành của thư viện.

Lợi ích của một kiến trúc tách biệt là nó cho phép các ngôn ngữ được nối vào cho các khía cạnh khác nhau của một ngăn xếp giao dịch, khi và khi yêu cầu thay đổi.


Thêm nữa