Construire une base de données quantitative de FMZ avec SQLite

Auteur:Je ne sais pas., Créé à: 2022-11-09 11:40:34, Mis à jour à: 2023-09-20 10:55:14

img

Résumé

Les données sont la source du trading quantitatif, comment gérer une grande quantité de données efficacement est un lien très critique, la base de données est l'une des meilleures solutions, de nos jours, l'application de la base de données est la norme quantitative pour tous les types de trading quotidien, de trading à haute fréquence et d'autres stratégies.https://www.fmz.com), y compris: comment créer des tableaux de données, stocker des données, modifier des données, supprimer des données, des données de référence et comment les appliquer dans la pratique.

Comment choisir la base de données

Ceux qui connaissent la plateforme FMZ Quant devraient savoir qu'avant de sauvegarder des données pour une réutilisation locale, vous ne pouvez utiliser que la fonction _G(), qui enregistre automatiquement les informations nécessaires à chaque fois que vous arrêtez la stratégie.

En ce qui concerne les bases de données auto-construites, vous devez penser à Oracle, MySQL, KDB, OneTick, NoSQL... Ce sont d'excellentes applications au niveau de l'entreprise en termes de fonctionnalité et de performance. Cependant, il y a aussi plusieurs problèmes: il est difficile de démarrer, et la configuration est lourde et la maintenance est difficile. Pour les traders quantitatifs de détail, c'est un peu comme tirer des mouches avec un canon. Même s'ils commencent, ils n'utilisent qu'une petite partie des fonctions.

Base de données intégrée de FMZ Quant

Ensuite, jetons un coup d'œil à la base de données légère intégrée par FMZ Quant. DBExec est une interface intégrée du système de gestion de données relationnelle de FMZ Quant. Il est développé sur la base de SQLite et est écrit en C. Il est non seulement de petite taille, peu de consommation de ressources, mais aussi rapide en traitement. Il est très approprié pour les amateurs d'analyse quantitative financière pour implémenter la gestion de données localement, car différents objets (tels que les échanges, les sources de données et les prix) peuvent être divisés en différents tableaux et les relations entre les tables peuvent être définies. En outre, les utilisateurs n'ont pas besoin de les installer et de les configurer séparément. Ils peuvent les utiliser directement en appelant la fonction DBExec)!

En outre, il est très facile d'apprendre le langage SQLite, et la plupart du travail effectué sur la base de données est complété par des instructions SQLite. Si vous connaissez la grammaire de base, vous pouvez répondre à la plupart des exigences. Voici la grammaire de base de SQLite.

Grammaire de base

La grammaire de SQLite est insensible aux petites et moyennes lettres, bien qu'il existe certaines commandes qui sont sensibles aux petites et moyennes lettres, telles que GLOB et glob, qui représentent des significations différentes. Les instructions SQLite peuvent commencer par n'importe quel mot-clé, tels que SELECT, INSERT, UPDATE, DELETE, ALTER, DROP, etc., ce qui signifie: extraire des données, insérer des données, mettre à jour des données, supprimer des données, modifier une base de données et supprimer une table de données. Toutes les instructions sont terminées par des points-virgules en anglais. Ce qui suit est une simple création de base de données, ajouter, supprimer, modifier et vérifier les opérations:

function main() {
    // Create: If the "users" table does not exist, create one, "id" is an integer and is incremented automatically, "name" is in text form and is not empty
    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('Zhang San')"));
    Log(DBExec("INSERT INTO users(name) values('Li Si')"));
    
    // Delete:
    Log(DBExec("DELETE FROM users WHERE id=1;"));
    
    // Modify:
    Log(DBExec("UPDATE users SET name='Wang Wu' WHERE id=2"));
    
    // Search:
    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"));
}

Une base de données contient généralement une ou plusieurs tables, chaque table est identifiée par un nom, notez que les tables réservées au système sont: kvdb, cfg, log, profit, graphique. c.-à-d. lors de la création de tables, vous devez éviter les noms réservés au système.

img

Exemples de stratégie

Après avoir appris la grammaire de base de SQLite, nous frappons pendant que le fer est chaud pour créer une instance de collecte et d'utilisation de données Tick en utilisant la base de données intégrée de FMZ Quant.

Étape 1: Mettre à jour le docker

Tout d'abord, assurez-vous que vous utilisez la dernière version du docker. Si vous avez téléchargé et utilisé le docker avant, vous devez le supprimer d'abord, puis le télécharger à nouveau et le redéployer surhttps://www.fmz.com/m/add-node page.

Étape 2: Créer une stratégie

function main() {
    // Subscribe contracts
    _C(exchange.SetContractType, 'swap');
    
    // Create 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);'
    ));
    
    // Get 10 pieces of tick data
    while (true) {
        let tick = exchange.GetTicker();
        // Add data to 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})`);
        // Search all data
        let allDate = DBExec('select * from tick');
        if (allDate.values.length > 10) {
            break;
        }
        Sleep(1000);
    }
    
    // Search all data
    Log(DBExec('select * from tick'));
    
    // Search the first data
    Log(DBExec('select * from tick limit 1'));
    
    // Search first two pieces of 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'));
    
    // Search all data
    let allDate = DBExec('select * from tick')
    Log(allDate);
}

Étape 3: mettre en œuvre la stratégie

Prenons Windows comme exemple, après avoir exécuté la stratégie, un dossier nommé d'après le numéro de robot sera créé dans le répertoire \logs\storage du répertoire docker.

img

Le code ci-dessus crée d'abord une table de données nommée tick, puis ajoute le champ de données de tick à la table, puis obtient les données de tick de l'échange dans la boucle, et insère les données dans la table de données tick. Dans le même temps, nous jugeons que la quantité de données dans la table de données dépasse 10, puis nous sautons de la boucle. Enfin, nous utilisons 5 commandes SQLite pour rechercher, supprimer et modifier les données dans la table de données respectivement. Et les imprimer dans les journaux, comme indiqué dans l'image suivante:

img

Étape 4: Créer une barre d'état

Enfin, nous ajoutons un peu de code pour créer une barre d'état pour la stratégie en obtenant les données dans la base de données FMZ Quant pour afficher les données plus visuellement, le code d'ajout montre comme suit:

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

Le code ci-dessus crée une table Binance Tick data à travers les données de la base de données. Le champ colonnes dans la base de données représente les lignes dans la barre d'état, et le champ values représente les colonnes dans la barre d'état. Comme indiqué dans la figure ci-dessous:

img

Code de stratégie complet

/*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;'));
    // Subscribe contracts
    _C(exchange.SetContractType, 'swap');

    // Create 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 pieces of tick data
    while (true) {
        let tick = exchange.GetTicker();
        // Add data to 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})`);
        // Search all data
        let allDate = DBExec('select * from tick');
        if (allDate.values.length > 10) {
            break;
        }
        Sleep(1000);
    }

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

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

    // Search first two pieces of 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'));

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

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

Cliquez sur ce lien.https://www.fmz.com/strategy/388963pour copier le code complet de la stratégie.

Base de données de mémoire

Si vous ne voulez pas enregistrer les données sur le disque en permanence, vous pouvez ajouter le symbole : avant l'instruction SQL pour fonctionner dans la base de données de mémoire, et les données seront réinitialisées après le redémarrage du robot.

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

Résumé

La base de données peut non seulement contenir des données massives, mais aussi le rêve de nombreux amateurs de trading quantitatif.


Relationnée

Plus de