Exchange object progress

This commit is contained in:
Ziver Koc 2021-04-29 01:11:16 +02:00
parent 4db1f866f3
commit 7f1933576b
15 changed files with 11013 additions and 43 deletions

View file

@ -15,9 +15,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
@ -49,7 +47,6 @@ public class TraderContext {
private static Properties dbConf = new Properties(); private static Properties dbConf = new Properties();
public static void initialize(){ public static void initialize(){
try { try {
// Read conf // Read conf
@ -76,7 +73,10 @@ public class TraderContext {
dbConf = db.exec("SELECT * FROM conf", new PropertiesSQLResult()); dbConf = db.exec("SELECT * FROM conf", new PropertiesSQLResult());
} }
// Upgrade DB needed? // --------------------------------------------
// Upgrade DB
// --------------------------------------------
DBConnection referenceDB = new DBConnection(DBConnection.DBMS.SQLite, DEFAULT_DB_FILE); DBConnection referenceDB = new DBConnection(DBConnection.DBMS.SQLite, DEFAULT_DB_FILE);
Properties defaultDBConf = Properties defaultDBConf =
referenceDB.exec("SELECT * FROM conf", new PropertiesSQLResult()); referenceDB.exec("SELECT * FROM conf", new PropertiesSQLResult());

View file

@ -1,8 +1,10 @@
package se.koc.trader; package se.koc.trader;
import se.koc.trader.api.ExchangeConfig;
import se.koc.trader.endpoint.AlertEndpoint; import se.koc.trader.endpoint.AlertEndpoint;
import se.koc.trader.api.TraderApiEndpoint; import se.koc.trader.api.TraderApiEndpoint;
import se.koc.trader.daemon.TraderMarketUpdateManager; import se.koc.trader.daemon.TraderMarketUpdateManager;
import se.koc.trader.struct.Exchange;
import se.koc.trader.struct.PluginConfig; import se.koc.trader.struct.PluginConfig;
import se.koc.trader.api.TraderPage; import se.koc.trader.api.TraderPage;
import zutil.db.DBConnection; import zutil.db.DBConnection;
@ -15,6 +17,7 @@ import zutil.plugin.PluginData;
import zutil.plugin.PluginManager; import zutil.plugin.PluginManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -29,6 +32,7 @@ public class TraderServer {
private static ScheduledExecutorService daemonExecutor; private static ScheduledExecutorService daemonExecutor;
private static HttpServer http; private static HttpServer http;
private static List<Class<? extends ExchangeConfig>> availableExchangeConfigs = new ArrayList<>();
public static void main(String[] args) throws SQLException { public static void main(String[] args) throws SQLException {
// init logging // init logging
@ -69,6 +73,16 @@ public class TraderServer {
TraderMarketUpdateManager marketUpdateManager = new TraderMarketUpdateManager(); TraderMarketUpdateManager marketUpdateManager = new TraderMarketUpdateManager();
marketUpdateManager.initialize(daemonExecutor); marketUpdateManager.initialize(daemonExecutor);
// ------------------------------------
// Init plugins configurations
// ------------------------------------
// Exchange
for (Iterator<Class<? extends ExchangeConfig>> it = pluginManager.getClassIterator(ExchangeConfig.class); it.hasNext(); ) {
availableExchangeConfigs.add(it.next());
}
// ------------------------------------ // ------------------------------------
// Init http server // Init http server
// ------------------------------------ // ------------------------------------
@ -98,4 +112,9 @@ public class TraderServer {
public static void registerPage(TraderPage page){ public static void registerPage(TraderPage page){
http.setPage(page.getId(), page); http.setPage(page.getId(), page);
} }
public static List<Class<? extends ExchangeConfig>> getAvailableExchangeConfigs() {
return availableExchangeConfigs;
}
} }

View file

@ -1,7 +1,9 @@
package se.koc.trader.page; package se.koc.trader.page;
import se.koc.trader.TraderContext; import se.koc.trader.TraderContext;
import se.koc.trader.TraderServer;
import se.koc.trader.api.TraderPage; import se.koc.trader.api.TraderPage;
import se.koc.trader.struct.ClassConfigurationData;
import se.koc.trader.struct.Exchange; import se.koc.trader.struct.Exchange;
import se.koc.trader.struct.Symbol; import se.koc.trader.struct.Symbol;
import zutil.ObjectUtil; import zutil.ObjectUtil;
@ -10,6 +12,7 @@ import zutil.io.file.FileUtil;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.parser.Templator; import zutil.parser.Templator;
import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -20,10 +23,14 @@ public class ExchangeConfigPage extends TraderPage {
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/exchange_config.tmpl"; private static final String TEMPLATE = TraderContext.RESOURCE_WEB_ROOT + "/exchange_config.tmpl";
private ArrayList<ClassConfigurationData> classConfigurations = new ArrayList<>();
public ExchangeConfigPage() { public ExchangeConfigPage() {
super("exchange_config"); super("exchange_config");
super.getRootNav().createSubNav("Settings").createSubNav(this.getId(), "Exchange Settings").setWeight(100); super.getRootNav().createSubNav("Settings").createSubNav(this.getId(), "Exchange Settings").setWeight(100);
for (Class c : TraderServer.getAvailableExchangeConfigs())
classConfigurations.add(new ClassConfigurationData(c));
} }
@Override @Override
@ -51,6 +58,7 @@ public class ExchangeConfigPage extends TraderPage {
if (exchange != null) { if (exchange != null) {
logger.info("Modifying exchange: " + exchange.getName()); logger.info("Modifying exchange: " + exchange.getName());
exchange.setName(request.get("name")); exchange.setName(request.get("name"));
exchange.setObjectClass(request.get("type"));
exchange.getObjectConfigurator().setValues(request).applyConfiguration(); exchange.getObjectConfigurator().setValues(request).applyConfiguration();
exchange.save(db); exchange.save(db);
@ -81,7 +89,9 @@ public class ExchangeConfigPage extends TraderPage {
// Output // Output
Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
tmpl.set("exchanges", Symbol.getSymbols(db)); tmpl.set("exchanges", Exchange.getExchanges(db));
tmpl.set("exchangeConfigClasses", TraderServer.getAvailableExchangeConfigs());
tmpl.set("exchangeObjectConfigs", classConfigurations);
return tmpl; return tmpl;

View file

@ -0,0 +1,18 @@
package se.koc.trader.struct;
import zutil.ui.Configurator;
import zutil.ui.Configurator.ConfigurationParam;
/**
* A Data class used by the dynamic class configuration pages
*/
public class ClassConfigurationData {
public Class clazz;
public ConfigurationParam[] params;
public ClassConfigurationData(Class clazz) {
this.clazz = clazz;
this.params = Configurator.getConfiguration(clazz);
}
}

View file

@ -6,6 +6,7 @@ import zutil.db.bean.DBBean;
import zutil.db.bean.DBBeanObjectDSO; import zutil.db.bean.DBBeanObjectDSO;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
/** /**
* Object representing a single exchange endpoint. * Object representing a single exchange endpoint.
@ -16,6 +17,9 @@ public class Exchange extends DBBeanObjectDSO<ExchangeConfig> {
private String name; private String name;
public static List<Exchange> getExchanges(DBConnection db) throws SQLException {
return DBBean.load(db, Exchange.class);
}
public static Exchange getExchange(DBConnection db, long id) throws SQLException { public static Exchange getExchange(DBConnection db, long id) throws SQLException {
return DBBean.load(db, Exchange.class, id); return DBBean.load(db, Exchange.class, id);
} }

Binary file not shown.

View file

@ -5,8 +5,8 @@
<div class="card-actions float-end"> <div class="card-actions float-end">
<div class="btn-group float-end" role="group"> <div class="btn-group float-end" role="group">
<button type="button" class="btn btn-success" <button type="button" class="btn btn-success"
data-toggle="modal" data-target="#exchangeModal" data-action="create_exchange"> data-bs-toggle="modal" data-bs-target="#exchangeModal" data-action="create_exchange">
<i class="bi bi-plus-square"></i> <i class="bi bi-plus"></i>
</button> </button>
</div> </div>
</div> </div>
@ -21,7 +21,7 @@
<th>Name</th> <th>Name</th>
<th>Type</th> <th>Type</th>
<th>Configuration</th> <th>Configuration</th>
<th>Actions</th> <th class="text-end">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -30,26 +30,25 @@
<td>{{.getName()}}</td> <td>{{.getName()}}</td>
<td>{{.getClass().getSimpleName()}}</td> <td>{{.getClass().getSimpleName()}}</td>
<td>{{.getDeviceConfig()}}</td> <td>{{.getDeviceConfig()}}</td>
<td> <td class="text-end">
<form method="POST"> <form method="POST">
<input type="hidden" name="id" value="{{.getId()}}"> <input type="hidden" name="id" value="{{.getId()}}">
<div class="btn-toolbar pull-right"> <div class="btn-group float-right">
<button type="button" class="btn btn-default btn-xs" data-toggle="modal" <button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#exchangeModal"
data-target="#exchangeModal"
data-action="modify_exchange" data-action="modify_exchange"
data-id="{{.getId()}}" data-id="{{.getId()}}"
data-name="{{.getName()}}" data-name="{{.getName()}}"
data-type="{{.getType()}}" data-type="{{.getObjectClass()}}"
{{#.getDeviceConfigurator().getConfiguration()}} {{#.getObjectConfigurator().getConfiguration()}}
data-{{.getName()}}="{{.getString()}}" data-{{.getName()}}="{{.getString()}}"
{{/.getDeviceConfigurator().getConfiguration()}} {{/.getObjectConfigurator().getConfiguration()}}
> >
<span class="glyphicon glyphicon-pencil"></span> <i class="bi bi-pencil"></i>
</button> </button>
<button type="submit" class="btn btn-danger btn-xs" name="action" value="remove_exchange"> <button type="submit" class="btn btn-danger btn-sm" name="action" value="remove_exchange">
<span class="glyphicon glyphicon-trash"></span> <i class="bi bi-small bi-trash"></i>
</button> </button>
</div> </div>
</form> </form>
@ -67,28 +66,41 @@
<!------------- MODALS ---------------> <!------------- MODALS --------------->
<script> <script>
$(function(){ $(function(){
initDynamicModalForm("exchangeModal"); initDynamicModalForm("exchangeModal", "exchange-conf-inputs", "exchange-conf-template");
}); });
</script> </script>
<div class="modal fade" id="exchangeModal" tabindex="-1"> <div class="modal fade" id="exchangeModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button> <h5 class="modal-title">Exchange</h5>
<h4 class="modal-title">Exchange</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<form method="POST"> <form method="POST">
<div class="modal-body"> <div class="modal-body">
<input type="hidden" id="action" name="action"> <input type="hidden" id="action" name="action">
<input type="hidden" id="id" name="id"> <input type="hidden" id="id" name="id">
<div class="form-group"> <div>
<label class="control-label">Name:</label> <label for="input-name" class="form-label">Name:</label>
<input type="text" class="form-control" name="name"> <input id="input-name" type="text" class="form-control" name="name">
</div>
<div>
<label for="input-type" class="form-label">Type:</label>
<select id="input-type" class="form-control" name="type">
{{#exchangeConfigClasses}}
<option>{{.getName()}}</option>
{{/exchangeConfigClasses}}
</select>
</div>
<hr>
<div id="exchange-conf-inputs">
<!-- Dynamic form -->
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="reset" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="reset" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button> <button type="submit" class="btn btn-primary">Save</button>
</div> </div>
</form> </form>
@ -96,3 +108,27 @@
</div> </div>
</div> </div>
<div id="exchange-conf-template" class="hidden">
{{#exchangeObjectConfigs}}
<div id="{{.clazz.getName()}}">
{{#.params}}
<div class="form-group">
<label for="input-{{.getName()}}" class="form-label">{{.getNiceName()}}:</label>
{{#.isTypeString()}}<input id="input-{{.getName()}}" type="text" class="form-control" name="{{.getName()}}">{{/#.isTypeString()}}
{{#.isTypeInt()}}<input id="input-{{.getName()}}" type="number" class="form-control" name="{{.getName()}}">{{/#.isTypeInt()}}
{{#.isTypeBoolean()}}<input id="input-{{.getName()}}" type="checkbox" name="{{.getName()}}" value="true">{{/#.isTypeBoolean()}}
{{#.isTypeEnum()}}
<select id="input-{{.getName()}}" class="form-control" name="{{.getName()}}">
{{#.getPossibleValues()}}<option>{{.}}</option>{{/.getPossibleValues()}}
</select>
{{/#.isTypeEnum()}}
{{#.getDescription()}}
<div class="form-text">{{.getDescription()}}</div>
{{/#.getDescription()}}
</div>
{{/.params}}
</div>
{{/exchangeObjectConfigs}}
</div>

10881
src/main/resources/web/js/jquery.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -65,23 +65,24 @@ function initDynamicModalForm(modalId, formTemplateId = null, templateID = null)
// read in all configurations into global variable (to skip naming issues) // read in all configurations into global variable (to skip naming issues)
if (formTemplateId != null) { if (formTemplateId != null) {
dynamicConf[formTemplateId] = []; dynamicConf[formTemplateId] = [];
$("#"+templateID+" div").each(function(){ $("#" + templateID + " div").each(function(){
dynamicConf[formTemplateId][$(this).attr("id")] = $(this).html(); dynamicConf[formTemplateId][$(this).attr("id")] = $(this).html();
}); });
// Update dynamic inputs // Update dynamic inputs
$("#"+modalId+" select[name=type]").change(function(){ $("#" + modalId + " select[name=type]").change(function(){
$("#"+modalId+" #"+formTemplateId).html(dynamicConf[formTemplateId][$(this).val()]); $("#" + modalId + " #"+formTemplateId).html(dynamicConf[formTemplateId][$(this).val()]);
}); });
} }
// click event // Listen to click event
$("#"+modalId).on('show.bs.modal', function (event) {
$("#" + modalId).on('show.bs.modal', function (event) {
var button = $(event.relatedTarget); var button = $(event.relatedTarget);
var modal = $(this); var modal = $(this);
// Reset all inputs // Reset all inputs
if (formTemplateId != null) if (formTemplateId != null)
modal.find("#"+formTemplateId).empty(); // clear form div modal.find("#" + formTemplateId).empty(); // clear form div
// select dynamic form // select dynamic form
var selector = modal.find("select[name=type]"); var selector = modal.find("select[name=type]");
@ -100,7 +101,7 @@ function initDynamicModalForm(modalId, formTemplateId = null, templateID = null)
if (value=="true") input.attr("checked", "true"); if (value=="true") input.attr("checked", "true");
else input.removeAttr("checked"); else input.removeAttr("checked");
// Add default false value as a unchecked checkbox is not included in the post // Add default false value as a unchecked checkbox is not included in the post
input.parent().prepend("<input type='hidden' name='"+input.attr("name")+"' value='false' />"); input.parent().prepend("<input type='hidden' name='" + input.attr("name") + "' value='false' />");
} else { } else {
input.val(value); input.val(value);
} }

View file

@ -1,6 +1,4 @@
var echarts = require('echarts'); /*var ROOT_PATH = 'https://echarts.apache.org/examples';
var ROOT_PATH = 'https://echarts.apache.org/examples';
var UP_COLOR = '#00da3c'; var UP_COLOR = '#00da3c';
var DOWN_COLOR = '#ec0000'; var DOWN_COLOR = '#ec0000';
@ -8,8 +6,8 @@ var DOWN_COLOR = '#ec0000';
$.get(ROOT_PATH + '/data/asset/data/stock-DJI.json', function (rawData) { $.get(ROOT_PATH + '/data/asset/data/stock-DJI.json', function (rawData) {
var data = splitData(rawData); var data = splitData(rawData);
initTradeChart(elementID, data) initTradeChart(elementID, data)
} });
*/
function splitData(rawData) { function splitData(rawData) {
var categoryData = []; var categoryData = [];
@ -223,4 +221,4 @@ function initTradeChart(elementID, data) {
}, },
] ]
}, true); }, true);
}); }

View file

@ -15,6 +15,7 @@
<link href="css/trader.css" rel="stylesheet"> <link href="css/trader.css" rel="stylesheet">
<!-- Javascript --> <!-- Javascript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.bundle.min.js"></script> <script src="js/bootstrap.bundle.min.js"></script>
<script src="js/bootstrap-switch.min.js"></script> <script src="js/bootstrap-switch.min.js"></script>
<script src="js/echarts.min.js"></script> <script src="js/echarts.min.js"></script>

View file

@ -26,7 +26,7 @@
<th>Type</th> <th>Type</th>
<th>Configuration</th> <th>Configuration</th>
<th> <th>
<button class="btn btn-default btn-xs pull-right" data-toggle="modal" <button class="btn btn-default btn-sm pull-right" data-toggle="modal"
data-target="#symbolModal" data-target="#symbolModal"
data-action="create_symbol"> data-action="create_symbol">
<span class="glyphicon glyphicon-plus"></span> <span class="glyphicon glyphicon-plus"></span>
@ -45,7 +45,7 @@
<input type="hidden" name="id" value="{{.getId()}}"> <input type="hidden" name="id" value="{{.getId()}}">
<div class="btn-toolbar pull-right"> <div class="btn-toolbar pull-right">
<button type="button" class="btn btn-default btn-xs" data-toggle="modal" <button type="button" class="btn btn-default btn-sm" data-toggle="modal"
data-target="#symbolModal" data-target="#symbolModal"
data-action="modify_symbol" data-action="modify_symbol"
data-id="{{.getId()}}" data-id="{{.getId()}}"
@ -58,7 +58,7 @@
<span class="glyphicon glyphicon-pencil"></span> <span class="glyphicon glyphicon-pencil"></span>
</button> </button>
<button type="submit" class="btn btn-danger btn-xs" name="action" value="remove_symbol"> <button type="submit" class="btn btn-danger btn-sm" name="action" value="remove_symbol">
<span class="glyphicon glyphicon-trash"></span> <span class="glyphicon glyphicon-trash"></span>
</button> </button>
</div> </div>

BIN
trader.db

Binary file not shown.

BIN
trader.db.0001 Normal file

Binary file not shown.