Documentation

Applications

Dernière mise à jour le 10. 2. 2022 par Mark Fric

Enregistrer les résultats de la banque de données dans la base de données

Cet exemple concerne l'enregistrement du contenu d'une banque de données dans une base de données, mis en œuvre sous la forme d'un extrait d'analyse personnalisée.

 

Note : Il y a eu un petit bug dans l'extension originale. Il y avait un petit bug dans l'extension originale - elle utilisait un paquet qui n'était pas encore disponible dans la version publiée de SQ X. Veuillez télécharger à nouveau le snippet.

 

Il utilise la base de données SQLite pour plus de simplicité, mais il n'y a aucun problème à utiliser MySql ou MariaDB ou toute autre base de données, car il utilise la connexion de base de données JDBC qui est un standard Java pour la connexion et la communication avec les bases de données.
Si vous utilisez une autre base de données, vous devrez.. :

  • modifier la chaîne de connexion JDBC dans createDBConnection() méthode
  • il peut être nécessaire d'ajouter la bibliothèque JDBC de votre base de données cible - SQLite est déjà inclus dans SQX, mais des bases de données comme MySql ou MariaDB ne le sont pas - vous devrez donc trouver sa bibliothèque JDBC (quelque chose comme https://dev.mysql.com/downloads/connector/j/ et ajoutez le(s) fichier(s) JAR dans le dossier {installation de StrategyQuant}/user/libs.

assez complexe, car il enregistre la vue exacte de la banque de données que vous voyez dans l'interface utilisateur - si vous ne voulez pas utiliser la vue, vous pouvez simplement obtenir des valeurs comme le bénéfice net, le nombre de transactions, etc. à partir de ResultsGroup et les enregistrer de votre côté.

La logique principale est en fait très simple :

@Override
public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception {
    Databank databank = ProjectEngine.get(project).getDatabanks().get(databankName) ;
    if(databank == null){
        throw new Exception("Databank " + project + "/" + databankName + " doesn't exist") ;
    }

    DatabankTableView view = databank.getView() ;

    String tableName = getTableName(project, task, databankName) ;

    try (Connection dbConnection = createDBConnection(tableName, view)) {
        dbConnection.setAutoCommit(false) ;

        try (Statement stmt = dbConnection.createStatement()) {
            for (int a = 0 ; a < databankRG.size() ; a++) {
                ResultsGroup rg = databankRG.get(a) ;
                writeData(rg, view, tableName, stmt) ;
            }
        }

        dbConnection.commit() ;
    }

    return databankRG ;
}

Le code va créer une connexion à la base de données, créer une déclaration, puis parcourir les groupes de résultats stockés dans la banque de données et enregistrer chacun d'entre eux dans la base de données à l'aide d'une déclaration SQL standard.

 

Code complet de l'extrait (il peut également être téléchargé dans la pièce jointe à ce message) :

package SQ.CustomAnalysis ;

import com.strategyquant.lib.SQTime ;
import com.strategyquant.lib.SQUtils ;
import com.strategyquant.tradinglib.* ;
import com.strategyquant.tradinglib.databank.DatabankTableColumnEntry ;
import com.strategyquant.tradinglib.databank.DatabankTableView ;
import com.strategyquant.tradinglib.project.ProjectEngine ;
import org.joda.time.format.DateTimeFormat ;
import org.joda.time.format.DateTimeFormatter ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;

import java.sql.Connection ;
import java.sql.DriverManager ;
import java.sql.SQLException ;
import java.sql.Statement ;
import java.util.ArrayList ;
import java.util.HashMap ;

public class SaveDatabankToDB extends CustomAnalysisMethod {

    public static final Logger Log = LoggerFactory.getLogger("SaveDatabankToDB") ;

    private static final String TABLE_NAME_SEPARATOR = "__" ;
    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd-HHmm") ;

    public static final String TABLE_NAME = "databankData" ;

    private static final String STRATEGY_COLUMN_NAME = "strategyName" ;

    //------------------------------------------------------------------------
    //------------------------------------------------------------------------
    //------------------------------------------------------------------------

    /**
     * Instancie une nouvelle méthode d'analyse personnalisée.
     */
    public SaveDatabankToDB() {
        super("SaveDatabankToDB", TYPE_PROCESS_DATABANK) ;
    }


    //------------------------------------------------------------------------

    @Override
    public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception {
        return true ;
    }

    //------------------------------------------------------------------------

    @Override
    public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception {
        Databank databank = ProjectEngine.get(project).getDatabanks().get(databankName) ;
        if(databank == null){
            throw new Exception("Databank " + project + "/" + databankName + " doesn't exist") ;
        }

        DatabankTableView view = databank.getView() ;

        String tableName = getTableName(project, task, databankName) ;

        try (Connection dbConnection = createDBConnection(tableName, view)) {
            dbConnection.setAutoCommit(false) ;

            try (Statement stmt = dbConnection.createStatement()) {
                for (int a = 0 ; a < databankRG.size() ; a++) {
                    ResultsGroup rg = databankRG.get(a) ;
                    writeData(rg, view, tableName, stmt) ;
                }
            }

            dbConnection.commit() ;
        }

        return databankRG ;
    }

    //------------------------------------------------------------------------

    public static String getOutputFolder(){
        return "C:/SQDatabankExports" ;
    }

    //------------------------------------------------------------------------

    private Connection createDBConnection(String tableName, DatabankTableView view) throws Exception {
        Connexion c = null ;

        try {
            Class.forName("org.sqlite.JDBC") ;
            String folderPath = getOutputFolder() ;

            SQUtils.ensureDirExists(folderPath) ;

            String dbPath = String.format("%s/%s.db", folderPath, tableName) ;
            String connectionString = String.format("jdbc:sqlite:%s", dbPath) ;

            c = DriverManager.getConnection(connectionString) ;

            tryCreateTable(c, tableName, view) ;
        }
        catch (Exception e ) {
            Log.error("Creating database connection failed", e) ;
            throw e ;
        }

        return c ;
    }

    //------------------------------------------------------------------------

    public static String getTableName(String projectName, String taskName, String databankName){
        String dateTime = dateTimeFormatter.print(System.currentTimeMillis()) ;
        return dateTime + TABLE_NAME_SEPARATOR + projectName + TABLE_NAME_SEPARATOR + taskName + TABLE_NAME_SEPARATOR + databankName ;
    }

    //------------------------------------------------------------------------

    private void tryCreateTable(Connection connection, String tableName, DatabankTableView view) throws Exception {
        if(view == null){
            lance une nouvelle Exception("La vue de la banque de données est nulle") ;
        }

        Statement stmt = null ;
        try {
            StringBuilder sb = new StringBuilder(STRATEGY_COLUMN_NAME).append(" TEXT PRIMARY KEY ") ;

            ColumnNamesResolver columnNamesResolver = new ColumnNamesResolver() ;

            for(int a=0 ; a<view.columns.size() ; a++){
                DatabankTableColumnEntry column = view.columns.get(a) ;
                String columnName = columnNamesResolver.getColumnName(column) ;

                sb.append(",") ;
                sb.append(columnName) ;
                sb.append(" TEXT ") ;
            }

            String sql = String.format("CREATE TABLE IF NOT EXISTS %s (%s) ;", TABLE_NAME, sb) ;

            stmt = connection.createStatement() ;
            stmt.executeUpdate(sql) ;
        }
        finally {
            if(stmt != null) {
                stmt.close() ;
            }
        }
    }

    //------------------------------------------------------------------------

    private void writeData(ResultsGroup rg, DatabankTableView view, String tableName, Statement stmt) throws SQLException {
        StringBuilder columnNames = new StringBuilder() ;
        StringBuilder values = new StringBuilder() ;

        ColumnNamesResolver columnNamesResolver = new ColumnNamesResolver() ;

        columnNames.append(STRATEGY_COLUMN_NAME) ;
        values.append("'").append(rg.getName()).append("'") ;

        for (int a = 0 ; a < view.columns.size() ; a++) {
            DatabankTableColumnEntry column = view.columns.get(a) ;
            String columnName = columnNamesResolver.getColumnName(column) ;
            String value = "N/A" ;

            try {
                value = column.tableColumn.exportValue(rg, null, Directions.Both, PlTypes.Money, SampleTypes.FullSample) ;
            } catch (Exception e) {
                Log.error("Error getting value for strategy + " + rg.getName() + " and column " + columnName, e) ;
            }

            columnNames.append(",").append(columnName) ;
            values.append(",").append("'").append(value).append("'") ;
        }

        String sql = String.format("INSERT INTO %s (%s) VALUES (%s)", TABLE_NAME, columnNames, values) ;
        stmt.executeUpdate(sql) ;
    }

    //------------------------------------------------------------------------

    private class ColumnNamesResolver {

        private HashMap columnNameCounts = new HashMap() ;

        public String getColumnName(DatabankTableColumnEntry columnEntry){
            String columnName = columnEntry.tableColumn.getClass().getSimpleName() ;
            String finalColumnName = null ;

            //le code suivant prend en charge les colonnes multiples portant le même nom dans la vue de la banque de données
            Integer columnCount = columnNameCounts.get(columnName) ;
            if(columnCount != null){
                columnCount += 1 ;
                finalColumnName = columnName + columnCount ;
            }
            else {
                columnCount = 1 ;
                finalColumnName = columnName ;
            }

            columnNameCounts.put(columnName, columnCount) ;

            return finalColumnName ;
        }

    }
}

 

Cet article a-t-il été utile ? L'article était utile L'article n'était pas utile

S'abonner
Notification pour
1 Commentaire
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
Négociant en abeilles
25. 2. 2022 8:57 pm

c'est un très bon exemple. Il permet d'accélérer l'analyse des résultats.

Postes connexes