Documentazione

Applicazioni

Ultimo aggiornamento il 10. 2. 2022 da Mark Fric

Salvare i risultati della banca dati nel DB

Questo esempio riguarda il salvataggio dei contenuti della banca dati in un database, implementato come frammento di CustomAnalysis.

 

Nota! C'era un piccolo bug nell'estensione originale: utilizzava un pacchetto che non era ancora disponibile nella versione rilasciata di SQ X. Si prega di riscaricare lo snippet.

 

Utilizza il DB SQLite per semplicità, ma non c'è alcun problema a usare MySql o MariaDB o qualsiasi altro database, perché utilizza la connessione al database JDBC, uno standard Java per la connessione e la comunicazione con i database.
Quando si utilizza un altro database è necessario:

  • modificare la stringa di connessione JDBC in createDBConnection() metodo
  • potrebbe essere necessario aggiungere la libreria JDBC per il database di destinazione: SQLite è già incluso in SQX, ma database come MySql o MariaDB non lo sono, quindi è necessario trovare la sua libreria JDBC (qualcosa come https://dev.mysql.com/downloads/connector/j/ e aggiungere i file JAR nella cartella {installazione di StrategyQuant}/user/libs.

Se non si vuole usare la vista, si possono semplicemente ottenere valori come Profitto netto, Numero di operazioni, ecc. da ResultsGroup e salvarli per conto proprio.

La logica principale è in realtà molto semplice:

@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;
}

Il codice creerà una connessione al DB, creerà una dichiarazione, quindi esaminerà i gruppi di risultati memorizzati nella banca dati e salverà ciascuno di essi nel DB utilizzando un'istruzione SQL standard.

 

Codice completo dello snippet (può essere scaricato anche in allegato a questo post):

pacchetto SQ.CustomAnalysis;

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

importare java.sql.Connection;
importare java.sql.DriverManager;
importare java.sql.SQLException;
importare java.sql.Statement;
importare java.util.ArrayList;
importare 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";

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

    /**
     * Istanzia un nuovo metodo di analisi personalizzato.
     */
    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 {
        Connection 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("Creazione connessione al database fallita", 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){
            throw new Exception("Databank view is null");
        }

        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("Errore nell'ottenere il valore per la strategia + " + rg.getName() + " e la colonna " + 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;

            //Il codice che segue si occupa di più colonne con lo stesso nome all'interno della vista banca dati
            Integer columnCount = columnNameCounts.get(columnName);
            if(columnCount != null){
                columnCount += 1;
                finalColumnName = columnName + columnCount;
            }
            altrimenti {
                columnCount = 1;
                finalColumnName = columnName;
            }

            columnNameCounts.put(columnName, columnCount);

            restituisce finalColumnName;
        }

    }
}

 

Questo articolo è stato utile? L'articolo è stato utile L'articolo non è stato utile

Abbonarsi
Notificami
1 Commento
Il più vecchio
Più recente I più votati
Feedback in linea
Visualizza tutti i commenti
Commerciante di api
25. 2. 2022 20:57

Questo è un ottimo esempio. Aiuta a velocizzare l'analisi dei risultati.

Messaggi correlati