ドキュメントとユーザーガイド
インスピレーションを与えるチュートリアルで、基礎を学ぶ、またはスキルを磨きましょう。.
最終更新日:2022年10月2日(マーク・フリック)
データバンクの結果をDBに保存する
この例は、カスタムアナリシススニペットとして実装された、データバンクの内容をデータベースに保存する方法に関するものです。.
注意!元の拡張機能には小さなバグがありました。SQ Xのリリース版ではまだ利用できないパッケージを使用していたためです。スニペットを再度ダウンロードしてください。.
シンプルさを求めてSQLite DBを使用していますが、データベースとの接続および通信を行うJavaの標準であるJDBCデータベース接続を使用しているため、MySQLやMariaDB、その他のデータベースを使用しても何の問題もありません。.
別のデータベースを使用する場合は、次の作業が必要になります:
- JDBC接続文字列を変更する createDBConnection() 方法
- 対象データベースのJDBCライブラリを追加する必要があるかもしれません。SQLiteはすでにSQXに含まれていますが、MySQLやMariaDBなどのデータベースは含まれていないため、JDBCライブラリを見つける必要があります(次のようなもの: https://dev.mysql.com/downloads/connector/j/ そして、そのJARファイルを{StrategyQuantのインストール先}/user/libsフォルダに追加します。.
UIに表示されている正確なデータベースビューを保存するためかなり複雑ですが、ビューを使用しない場合は、ResultsGroupから純利益や取引回数などの値単純に取得して自分で保存することができます。.
実際のメインロジックは非常にシンプルです:
@Override
public ArrayList<ResultsGroup> processDatabank(String project, String task, String databankName, ArrayList<ResultsGroup> 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;
}
コードはDB接続を作成し、Statementを作成してから、データベースに保存されているResultGroupsを順に処理し、標準的なSQL文を使用してそれぞれをDBに保存します。.
スニペットの完全なコード(この投稿の添付ファイルからダウンロードすることもできます):
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";
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
/**
* Instantiates a new custom analysis method.
*/
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<ResultsGroup> processDatabank(String project, String task, String databankName, ArrayList<ResultsGroup> 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("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){
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("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<String, Integer> columnNameCounts = new HashMap<>();
public String getColumnName(DatabankTableColumnEntry columnEntry){
String columnName = columnEntry.tableColumn.getClass().getSimpleName();
String finalColumnName = null;
//following code takes care of multiple columns with the same name inside databank view
Integer columnCount = columnNameCounts.get(columnName);
if(columnCount != null){
columnCount += 1;
finalColumnName = columnName + columnCount;
}
else {
columnCount = 1;
finalColumnName = columnName;
}
columnNameCounts.put(columnName, columnCount);
return finalColumnName;
}
}
}
この記事は参考になりましたか? この記事は役に立った この記事は役に立たなかった