Documentación

Aplicaciones

Última actualización el 10. 2. 2022 by Mark Fric

Guardar los resultados del banco de datos en la base de datos

Este ejemplo trata de guardar el contenido del banco de datos en una base de datos, implementado como un fragmento de CustomAnalysis.

 

Nota. Había un pequeño error en la extensión original: utilizaba un paquete que aún no estaba disponible en la versión liberada de SQ X. Por favor, vuelva a descargar el fragmento.

 

Utiliza SQLite DB por simplicidad, pero no hay problema para utilizar MySql o MariaDB o cualquier otra base de datos, ya que utiliza la conexión de base de datos JDBC que es un estándar de Java a la hora de conectarse y comunicarse con bases de datos.
Si utilizas otra base de datos tendrás que:

  • cambiar la cadena de conexión JDBC en createDBConnection() método
  • SQLite ya está incluido en SQX, pero bases de datos como MySql o MariaDB no lo están, por lo que tendrá que encontrar su biblioteca JDBC (algo así como https://dev.mysql.com/downloads/connector/j/ y añada su(s) archivo(s) JAR a la carpeta {StrategyQuant installation}/user/libs.

bastante complejo, porque guarda la vista exacta del banco de datos que se ve en la interfaz de usuario. Si no desea utilizar la vista, puede simplemente obtener valores como Beneficio neto, Número de operaciones, etc. de ResultsGroup y guardarlos por su cuenta.

En realidad, la lógica principal es muy sencilla:

@Override
public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception {
    Banco de datos databank = ProjectEngine.get(project).getDatabanks().get(databankName);
    if(databank == null){
        throw new Exception("El banco de datos " + proyecto + "/" + databankName + " no existe");
    }

    DatabankTableView view = databank.getView();

    String tableName = getTableName(proyecto, tarea, 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;
}

El código creará una conexión a la base de datos, creará una sentencia, luego recorrerá los grupos de resultados almacenados en la base de datos y guardará cada uno de ellos en la base de datos utilizando una sentencia SQL estándar.

 

Código completo del snippet (también se puede descargar en el archivo adjunto a este post):

paquete 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;
importar 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("aaaa-MM-dd-HHmm");

    public static final String TABLE_NAME = "databankData";

    private static final String STRATEGY_COLUMN_NAME = "strategyName";

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

    /**
     * Instancia de un nuevo método de análisis personalizado.
     */
    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 {
        Banco de datos databank = ProjectEngine.get(project).getDatabanks().get(databankName);
        if(databank == null){
            throw new Exception("El banco de datos " + proyecto + "/" + databankName + " no existe");
        }

        DatabankTableView view = databank.getView();

        String tableName = getTableName(proyecto, tarea, 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 {
        Conexión c = null;

        try {
            Clase.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("Error al crear conexión a base de datos", 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(vista == null){
            throw new Exception("La vista del banco de datos es nula");
        }

        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 columna = view.columns.get(a);
                String columnName = columnNamesResolver.getColumnName(column);

                sb.append(",");
                sb.append(nombrecolumna);
                sb.append(" TEXTO");
            }

            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 valores = 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 columna = view.columns.get(a);
            String columnName = columnNamesResolver.getColumnName(columna);
            String value = "N/A";

            try {
                value = column.tableColumn.exportValue(rg, null, Directions.Both, PlTypes.Money, SampleTypes.FullSample);
            } catch (Exception e) {
                Log.error("Error al obtener el valor de la estrategia + " + rg.getName() + " y la columna " + 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);
    }

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

    clase privada ColumnNamesResolver {

        private HashMap columnNameCounts = new HashMap();

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

            //el siguiente código se encarga de múltiples columnas con el mismo nombre dentro de la vista del banco de datos
            Integer columnCount = columnNameCounts.get(columnName);
            if(columnCount != null){
                columnCount += 1;
                finalColumnName = columnName + columnCount;
            }
            else {
                columnCount = 1;
                nombreColumna final = nombreColumna;
            }

            columnNameCounts.put(columnName, columnCount);

            return nombreColumnaFinal;
        }

    }
}

 

¿Le ha resultado útil este artículo? El artículo era útil El artículo no era útil

Suscríbase a
Notificar a
1 Comentario
Más antiguo
Más reciente Más votados
Feedbacks de Inline
Ver todos los comentarios
Comerciante de abejas
25. 2. 2022 8:57 pm

Este es un ejemplo muy bueno. Ayuda a acelerar el análisis de los resultados.

Puestos relacionados