Sử dụng SQLite để xây dựng cơ sở dữ liệu FMZ Quant

Tác giả:Ninabadass, Tạo: 2022-04-24 11:32:35, Cập nhật: 2022-04-24 16:21:38

Sử dụng SQLite để xây dựng cơ sở dữ liệu FMZ Quant [TOC]

Tóm tắt

Dữ liệu là nguồn của giao dịch định lượng. Nó rất quan trọng để quản lý hiệu quả một lượng lớn dữ liệu. Cơ sở dữ liệu là một trong những giải pháp tốt nhất. Ngày nay, ứng dụng cơ sở dữ liệu đã trở thành cấu hình định lượng tiêu chuẩn của các chiến lược giao dịch hàng ngày, giao dịch tần số cao và các chiến lược khác. Trong bài viết này, chúng ta sẽ nghiên cứu cơ sở dữ liệu tích hợp của FMZ Quant (FMZ.COM), bao gồm: cách tạo bảng dữ liệu, lưu dữ liệu, sửa đổi dữ liệu, xóa dữ liệu và dữ liệu tham chiếu, cũng như cách sử dụng nó trong thực tế.

Cách chọn cơ sở dữ liệu

Những người quen thuộc với nền tảng giao dịch lượng tử FMZ nên biết rằng trước đây, nếu bạn muốn lưu dữ liệu vào địa phương để sử dụng lại, bạn chỉ có thể sử dụng chức năng _G(). Mỗi khi bạn dừng chiến lược, chức năng _G() sẽ tự động lưu thông tin cần thiết. Nhưng nếu bạn muốn lưu dữ liệu định dạng phức tạp hơn, chức năng _G( rõ ràng là không phù hợp, vì vậy nhiều người nghĩ đến việc xây dựng cơ sở dữ liệu của riêng họ để giải quyết vấn đề.

Khi nói đến cơ sở dữ liệu tự xây dựng, mọi người có thể nghĩ đến Oracle, MySQL, KDB, OneTick, NoSQL... Tất cả những ứng dụng này đều là các ứng dụng cấp doanh nghiệp xuất sắc, cả về chức năng và hiệu suất. Nhưng cũng có một số vấn đề: khó bắt đầu, và cấu hình và bảo trì là khó khăn. Đối với các nhà đầu tư bán lẻ trong giao dịch định lượng, nó giống như phá vỡ ruồi trên bánh xe. Ngay cả khi bạn đã bắt đầu với các ứng dụng đó, chỉ một vài chức năng của chúng sẽ được sử dụng.

Cơ sở dữ liệu FMZ Quant

Tiếp theo, chúng ta hãy tìm hiểu cơ sở dữ liệu nhẹ của FMZ Quant. DBExec là giao diện hệ thống quản lý dữ liệu quan hệ được xây dựng trong FMZ Quant. Nó được phát triển dựa trên SQLite và được viết bằng C. Nó không chỉ có kích thước nhỏ, chiếm ít tài nguyên, mà còn có tốc độ xử lý rất nhanh. Nó rất phù hợp cho những người đam mê phân tích định lượng tài chính để thực hiện quản lý dữ liệu tại địa phương, bởi vì nó có thể chia các object khác nhau (như nền tảng, nguồn dữ liệu, giá) thành các bảng khác nhau và xác định mối quan hệ giữa các bảng. Ngoài ra, người dùng không cần cài đặt và cấu hình riêng biệt; miễn là họ gọi hàm DBExec, nó có thể được sử dụng trực tiếp!

Ngoài ra, chi phí học ngôn ngữ SQLite rất thấp, và hầu hết các công việc được thực hiện trên cơ sở dữ liệu được thực hiện bởi các câu lệnh SQLite. Hầu hết các nhu cầu có thể được đáp ứng bằng cách làm quen với cú pháp cơ bản.

Định nghĩa cơ bản

Phương pháp cú pháp của SQLite là không nhạy cảm với chữ cái lớn, nhưng một số lệnh là nhạy cảm với chữ cái lớn, chẳng hạn như GLOB và glob, có ý nghĩa khác nhau. Các lệnh SQLite có thể bắt đầu bằng bất kỳ từ khóa nào, chẳng hạn như SELECT, INSERT, UPDATE, DELETE, ALTER, DROP, v.v., có nghĩa là: trích xuất dữ liệu, chèn dữ liệu, cập nhật dữ liệu, xóa dữ liệu, sửa đổi cơ sở dữ liệu và xóa bảng dữ liệu. Tất cả các lệnh đều kết thúc bằng dấu chấm bán chấm.

function main() {
    // create: if the table of "users" do not exist, create one; "id" is integer and increases automatically; "name" is in form of text and not null 
    Log(DBExec('CREATE TABLE IF NOT EXISTS "users" (id INTEGER PRIMARY KEY AUTOINCREMENT, name text not NULL);'));
    
    // add: 
    Log(DBExec("INSERT INTO users(name) values('A')"));
    Log(DBExec("INSERT INTO users(name) values('B')"));
    
    // delete: 
    Log(DBExec("DELETE FROM users WHERE id=1;"));
    
    // modify:
    Log(DBExec("UPDATE users SET name='C' WHERE id=2"));
    
    // query:
    Log(DBExec('select 2, ?, ?, ?, ?', 'ok', true,9.8,null));
    Log(DBExec('select * from kvdb'));
    Log(DBExec('select * from cfg'));
    Log(DBExec('select * from log'));
    Log(DBExec('select * from profit'));
    Log(DBExec('select * from chart'));
    Log(DBExec("selEct * from users"));
}

Một cơ sở dữ liệu thường chứa một hoặc nhiều bảng, mỗi bảng có tên nhận dạng, cần lưu ý rằng các bảng được hệ thống lưu trữ là: kvdb, cfg, log, profit, chart. nghĩa là, khi tạo bảng, bạn nên tránh tên được hệ thống lưu trữ.img

Ví dụ về chiến lược

Sau khi biết cú pháp cơ bản của SQLite, hãy tấn công trong khi sắt nóng; sử dụng cơ sở dữ liệu định lượng FMZ Quant để tạo một trường hợp thu thập và sử dụng dữ liệu Tick.

Bước 1: cập nhật DockerĐầu tiên, hãy chắc chắn rằng bạn đang sử dụng phiên bản mới nhất của một docker. Nếu bạn đã tải xuống và sử dụng một docker trước đây, bạn cần phải xóa nó trước tiên, và tải xuống và triển khai nó một lần nữa trên trang (https://www.fmz.com/m/add-node).

Bước 2: Xây dựng chiến lược

function main() {
    // set contract 
    _C(exchange.SetContractType, 'swap');
    
    // create the data table 
    DBExec('CREATE TABLE IF NOT EXISTS "tick" (id INTEGER PRIMARY KEY AUTOINCREMENT,'.concat(
        'High FLOAT not NULL,', 
        'Low FLOAT not NULL,', 
        'Sell FLOAT not NULL,', 
        'Buy FLOAT not NULL,', 
        'Last FLOAT not NULL,', 
        'Volume INTEGER not NULL,', 
        'Time INTEGER not NULL);'
    ));
    
    // obtain 10 tick data 
    while (true) {
        let tick = exchange.GetTicker();
        // add data in the tick table 
        DBExec(`INSERT INTO tick(High, Low, Sell, Buy, Last, Volume, Time) values(${tick.High}, ${tick.Low}, ${tick.Sell}, ${tick.Buy}, ${tick.Last}, ${tick.Volume}, ${tick.Time})`);
        // query all data
        let allDate = DBExec('select * from tick');
        if (allDate.values.length > 10) {
            break;
        }
        Sleep(1000);
    }
    
    // query all data 
    Log(DBExec('select * from tick'));
    
    // query the first data 
    Log(DBExec('select * from tick limit 1'));
    
    // query the first two data 
    Log(DBExec('select * from tick limit 0,2'));
    
    // delete the first data 
    Log(DBExec('DELETE FROM tick WHERE id=1;'));
    
    // modify the second data 
    Log(DBExec('UPDATE tick SET High=10000 WHERE id=2'));
    
    // query all data 
    let allDate = DBExec('select * from tick')
    Log(allDate);
}

Bước 3: thực hiện chiến lượcLấy ví dụ như Windows. Sau khi chạy chiến lược, một thư mục được đặt tên với ID bot sẽ được tạo trong từ điển \logs\storage của thư mục docker; mở thư mục, và sẽ có một tệp với .db3 như là hậu tố; tệp này là tệp của cơ sở dữ liệu tích hợp FMZ Quant. Như được hiển thị trong hình sau:img

Mã trên đầu tiên tạo ra một bảng dữ liệu có tên tick, sau đó thêm trường dữ liệu tick vào bảng, sau đó lấy dữ liệu tick từ nền tảng trong vòng lặp, và chèn dữ liệu này vào bảng dữ liệu tick, và đồng thời Nếu được đánh giá là số lượng dữ liệu trong bảng dữ liệu vượt quá 10, nó sẽ nhảy ra khỏi vòng lặp. Cuối cùng, sử dụng năm lệnh SQLite để truy vấn, xóa và sửa đổi dữ liệu trong bảng dữ liệu. Và in nó ra trong nhật ký, như được hiển thị trong hình ảnh sau:img

Bước 4: tạo thanh trạng tháiCuối cùng, chúng tôi thêm một số đoạn mã để tạo một thanh trạng thái cho chiến lược bằng cách lấy dữ liệu trong cơ sở dữ liệu FMZ Quant để hiển thị dữ liệu một cách trực quan hơn.

    // create a status bar 
    let table = {
        type: 'table',
        title: 'Binance Tick data',
        cols: allDate.columns,
        rows: allDate.values
    }
    LogStatus('`' + JSON.stringify(table) + '`');

Mã trên tạo ra bảng Binance Tick Data từ dữ liệu trong cơ sở dữ liệu. trường cột trong cơ sở dữ liệu đại diện cho hàng ngang trong thanh trạng thái, và giá trị trường đại diện cho hàng dọc trong thanh trạng thái. Như được hiển thị bên dưới:img

Mã nguồn chiến lược đầy đủ

/*backtest
start: 2020-07-19 00:00:00
end: 2020-08-17 23:59:00
period: 15m
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"LTC_USDT"}]
*/

function main() {
    Log(DBExec('DROP TABLE tick;'));
    // set contract 
    _C(exchange.SetContractType, 'swap');

    // establish the data table 
    DBExec('CREATE TABLE IF NOT EXISTS "tick" (id INTEGER PRIMARY KEY AUTOINCREMENT,'.concat(
        'High FLOAT not NULL,',
        'Low FLOAT not NULL,',
        'Sell FLOAT not NULL,',
        'Buy FLOAT not NULL,',
        'Last FLOAT not NULL,',
        'Volume INTEGER not NULL,',
        'Time INTEGER not NULL);'
    ));

    // obtain 10 tick data 
    while (true) {
        let tick = exchange.GetTicker();
        // add data in the tick table
        DBExec(`INSERT INTO tick(High, Low, Sell, Buy, Last, Volume, Time) values(${tick.High}, ${tick.Low}, ${tick.Sell}, ${tick.Buy}, ${tick.Last}, ${tick.Volume}, ${tick.Time})`);
        // query all data 
        let allDate = DBExec('select * from tick');
        if (allDate.values.length > 10) {
            break;
        }
        Sleep(1000);
    }

    // query all data 
    Log(DBExec('select * from tick'));

    // query the first data 
    Log(DBExec('select * from tick limit 1'));

    // query the first two data 
    Log(DBExec('select * from tick limit 0,2'));

    // delet the first data 
    Log(DBExec('DELETE FROM tick WHERE id=1;'));

    // modify the second data
    Log(DBExec('UPDATE tick SET High=10000 WHERE id=2'));

    // query all data 
    let allDate = DBExec('select * from tick')
    Log(allDate);

    // create the status bar 
    let table = {
        type: 'table',
        title: 'Binance Tick data',
        cols: allDate.columns,
        rows: allDate.values
    }
    LogStatus('`' + JSON.stringify(table) + '`');
}

Nhấp vào liên kết:https://www.fmz.com/strategy/265906, và bạn có thể sao chép toàn bộ mã nguồn.

Cơ sở dữ liệu trong bộ nhớ

Nếu các dữ liệu vận hành không muốn được lưu vĩnh viễn vào ổ đĩa, bạn có thể thêm:ký hiệu trước câu lệnh SQL để hoạt động trong cơ sở dữ liệu trong bộ nhớ, và dữ liệu sẽ được đặt lại sau khi bot khởi động lại.

DBExec(":select 1,2,3");

Kết luận

Cơ sở dữ liệu không chỉ có thể mang lại dữ liệu khổng lồ, mà còn mang lại những giấc mơ của nhiều người đam mê giao dịch định lượng. Việc sử dụng cơ sở dữ liệu không giới hạn trong các ví dụ được đề cập trong bài viết. Để biết thêm các phương pháp sử dụng, bạn có thể tham khảo hướng dẫn SQLite và loạt bài viết sẽ được đăng trên FMZ Quant sau này.


Thêm nữa