Compare commits

...

2 Commits

11 changed files with 172 additions and 15 deletions

View File

@ -260,7 +260,7 @@ export default class BinanceApiClient extends APIClient {
"symbol": transaction.symbol.getKey(),
"side": "BUY",
"type": "LIMIT",
"price": transaction.buySettings.oderPrice,
"price": transaction.buySettings.orderPrice,
"quantity" : transaction.buySettings.orderQuantity,
"newClientOrderId": transaction.id,
"timeInForce": "GTC",
@ -283,7 +283,7 @@ export default class BinanceApiClient extends APIClient {
"symbol": transaction.symbol.getKey(),
"side": "SELL",
"type": "LIMIT",
"price": transaction.sellSettings.oderPrice,
"price": transaction.sellSettings.orderPrice,
"quantity" : transaction.sellSettings.orderQuantity,
"newClientOrderId": transaction.id,
"timeInForce": "GTC",

View File

@ -11,7 +11,7 @@ export default class TransactionSettings extends Serializable{
* ordered price
* @type {number}
*/
oderPrice = 0;
orderPrice = 0;
/**
* real quantity
@ -37,7 +37,7 @@ export default class TransactionSettings extends Serializable{
*/
constructor(price = 0, quantity = 0){
super();
this.oderPrice = price;
this.orderPrice = price;
this.orderQuantity = quantity;
}
@ -47,7 +47,7 @@ export default class TransactionSettings extends Serializable{
toJson() {
const obj = JSON.parse(super.toJson());
obj.orderQuantity = this.orderQuantity;
obj.oderPrice = this.oderPrice;
obj.oderPrice = this.orderPrice;
obj.quantity = this.quantity;
obj.price = this.price;
obj.apiID = this.apiID;
@ -64,7 +64,7 @@ export default class TransactionSettings extends Serializable{
const tmpObj = JSON.parse(objString);
obj.orderQuantity = tmpObj.orderQuantity;
obj.oderPrice = tmpObj.oderPrice;
obj.orderPrice = tmpObj.oderPrice;
obj.quantity = tmpObj.quantity;
obj.price = tmpObj.price;
obj.apiID = tmpObj.apiID;

View File

@ -20,13 +20,15 @@ import StatisticWorker from "./tradingbot/worker/StatisticWorker.js";
import PeakDetector from "./tradingbot/data/asset/PeakDetector.js";
import OrderBookEntry from "./apiwrapper/orderbook/OrderBookEntry.js";
import TestStrategy from "./tradingbot/strategy/TestStrategy.js";
import AvgMinMaxStrategy from "./tradingbot/strategy/AvgMinMaxStrategy.js";
try{
const tradingBot = new TradingBot("C:/Users/Wlad/Projekte/BinanceBot/binance_bot/data/conf", "config-test.sjson");
const galaWorker = new DefaultWorker("default_gala", TradingPairs.GALAUSDT, new AbstractStrategy());
const galaWorker = new DefaultWorker("gala_minmax", TradingPairs.GALAUSDT, new AvgMinMaxStrategy());
const statWorker = new StatisticWorker("gala_stats", TradingPairs.GALAUSDT, new TestStrategy());
tradingBot.registerWorker(galaWorker);
tradingBot.registerWorker(statWorker);
//tradingBot.registerWorker(galaWorker);
//tradingBot.registerWorker(statWorker);
tradingBot.start();
} catch (e){
console.log(e);
@ -95,11 +97,13 @@ try{
// ############################
/*const path = 'C:/Users/Wlad/Projekte/BinanceBot/binance_bot/data/conf';
const conf = new BotConfig();
conf.setApiConfig(BinanceApiConfig.createMainNetConfig());
conf.setWorkingDirectory('C:/Users/Wlad/Desktop/binance_bot');
conf.setApiConfig(BinanceApiConfig.createTestNetConfig());
conf.setWorkingDirectory('C:/Users/Wlad/Projekte/BinanceBot/binance_bot/data');
conf.setRelativeDataPath('data');
conf.setRelativeLogPath('logs');
conf.setRelativeTmpPath('tmp');
conf.setUsdTradeLimit(500);
conf.setPerTradeLimit(30);
SerializableHelper.save(path, "config-test.sjson", conf);*/
// ############################

View File

@ -71,7 +71,7 @@ export default class AssetDataCollector {
const tp = tradingPair instanceof TradingPair ? tradingPair : TradingPairs.fromString(symbol);
if(!this.#assetMap.has(tp.getKey())){
this.#assetMap.set(tp.getKey(), new AssetData(tp, this.#config.getDataCollectionConfig()));
this.#assetMap.set(tp.getKey(), new AssetData(tp));
}
return this.#assetMap.get(tp.getKey());

View File

@ -344,12 +344,12 @@ export default class TradingBot {
* @param {number} price
*/
requestBuy(worker, quantity, price){
if(this.#config.getUsdTradeLimit() / this.#config.getPerTradeLimit() >= this.#transactions.length){
if(this.#config.getUsdTradeLimit() / this.#config.getPerTradeLimit() <= this.#transactions.length){
return;
}
const transaction = new Transaction(worker.getId(), worker.getTradingPair());
transaction.buySettings.oderPrice = price;
transaction.buySettings.orderPrice = price;
transaction.buySettings.orderQuantity = Math.round(this.#config.getPerTradeLimit() / price);
this.#transactions.push(transaction);
this.#saveTransactions();

View File

@ -0,0 +1,33 @@
import AggregatedDataPoint from "../data/asset/AggregatedDataPoint";
export default class AssetInstrumentCalculator{
/**
* Calculate simple moving average
*
* Formula: SMA = (A1 + A2 + .An) / n
*
* @param {AggregatedDataPoint[]} dataPoints
* @returns {number}
*/
static calculateSMA(dataPoints) {
return dataPoints.map(dp => dp.avgPrice).reduce((a, b) => a+b, 0) / dataPoints.length;
}
/**
* Calculate exponential moving average
*
* Formula: EMA = [Closing Price EMA (Previous Time Period)] x Multiplier + EMA (Previous Time Period)
*
* SMA is taken as EMA of previous period; Multiplier ist 2/(n+1)
*
* @param {AggregatedDataPoint[]} dataPoints
* @returns {number}
*/
static caclulateEMA(dataPoints) {
const sma = AssetInstrumentCalculator.calculateSMA(dataPoints);
const multiplier = 2 / (dataPoints.length + 1);
return sma * (1 - multiplier) + dataPoints[dataPoints.length - 1] * multiplier;
}
}

View File

@ -27,7 +27,7 @@ export default class DefaultWorker extends AbstractWorker{
* @param {Transaction[]} transactions
*/
onUpdate(assetData, transactions){
this.getStrategy().updateAssetData(assetData);
this.getStrategy().setAssetData(assetData);
const price = this.getStrategy().getAssetData().getOrderBook().getBestBid().price;
if(this.getStrategy().shouldBuy()){

View File

@ -4,6 +4,7 @@ import cors from "cors";
import WebViewDataProvider from "./WebViewDataProvider.js";
import ConverterFactory from "./converter/ConverterFactory.js";
import AggregatedDataPointConverter from "./converter/converters/AggregatedDataPointConverter.js";
import TransactionConverter from "./converter/converters/TransactionConverter.js";
export default class RestClient {
@ -64,6 +65,10 @@ export default class RestClient {
res.json(this.#getAssetOrderBook(req.params.symbol));
});
this.#service.get("/asset/:symbol/transactions", (req, res, next) => {
res.json(this.#getTransactions(req.params.symbol, req.query.type));
});
this.#service.get("/asset/:symbol/aggregated", (req, res, next) => {
res.json(this.#getAggregatedAssetData(req.params.symbol, req.query.startTime, req.query.duration));
});
@ -100,6 +105,14 @@ export default class RestClient {
return ConverterFactory.getConverter(orderBook).toRestObject(orderBook);
}
#getTransactions(asset, type = null){
const allTransactions = type == "all";
const transactions = allTransactions ? this.#dataProvider.getAllTransactions(asset) : this.#dataProvider.getActiveTransactions(asset);
const transactionConverter = new TransactionConverter();
return transactions.map(t => transactionConverter.toRestObject(t));
}
#getAllOrderBooks(){
const orderBooks = [];

View File

@ -1,15 +1,21 @@
import OrderBook from "../../apiwrapper/orderbook/OrderBook.js";
import OrderBookEntry from "../../apiwrapper/orderbook/OrderBookEntry.js";
import Transaction from "../../apiwrapper/transaction/Transaction.js";
import TransactionSettings from "../../apiwrapper/transaction/TransactionSettings.js";
import AggregatedDataPoint from "../../tradingbot/data/asset/AggregatedDataPoint.js";
import AbstractConverter from "./AbstractConverter.js";
import AggregatedDataPointConverter from "./converters/AggregatedDataPointConverter.js";
import OrderBookConverter from "./converters/OrderBookConverter.js";
import OrderBookEntryConverter from "./converters/OrderBookEntryConverter.js";
import TransactionConverter from "./converters/TransactionConverter.js";
import TransactionSettingsConverter from "./converters/TransactionSettingsConverter.js";
export default class ConverterFactory {
static OBJECT_TYPE_ORDER_BOOK = 'order_book';
static OBJECT_TYPE_ORDER_BOOK_ENTRY = 'order_book_entry';
static OBJECT_TYPE_AGGREGATED_DATA_POINT = 'aggregated_data_point';
static OBJECT_TYPE_TRANSACTION = 'transaction';
static OBJECT_TYPE_TRANSACTION_SETTINGS = 'transaction_settings';
/**
* @param {any} obj
@ -30,6 +36,10 @@ export default class ConverterFactory {
return new OrderBookEntryConverter();
} else if (obj instanceof AggregatedDataPoint){
return new AggregatedDataPointConverter();
} else if (obj instanceof Transaction){
return new TransactionConverter();
} else if (obj instanceof TransactionSettings){
return new TransactionSettingsConverter();
}
throw new Error("No converter defined for: " + JSON.stringify(obj));
@ -47,6 +57,10 @@ export default class ConverterFactory {
return new OrderBookEntryConverter();
case this.OBJECT_TYPE_AGGREGATED_DATA_POINT:
return new AggregatedDataPointConverter();
case this.OBJECT_TYPE_TRANSACTION:
return new TransactionConverter();
case this.OBJECT_TYPE_TRANSACTION_SETTINGS:
return new TransactionSettingsConverter();
default:
throw new Error("No converter defined for type: " + type);
}

View File

@ -0,0 +1,52 @@
import TradingPairs from "../../../apiwrapper/assets/TraidingPairs.js";
import Transaction from "../../../apiwrapper/transaction/Transaction.js";
import AbstractConverter from "../AbstractConverter.js";
import ConverterFactory from "../ConverterFactory.js";
import TransactionSettingsConverter from "./TransactionSettingsConverter.js";
export default class TransactionConverter extends AbstractConverter {
constructor(){
super();
}
/**
* @param {Transaction} obj
* @returns {object}
*/
toRestObject(obj) {
const tsConverter = new TransactionSettingsConverter();
return {
_objectType: ConverterFactory.OBJECT_TYPE_TRANSACTION,
id: obj.id,
initiator: obj.initiator,
phase: obj.phase,
timestamp:obj.timestamp,
result: obj.result,
buySettings: tsConverter.toRestObject(obj.buySettings),
sellSettings: tsConverter.toRestObject(obj.sellSettings),
symbol: obj.symbol.getKey()
};
}
/**
* @param {object} obj
* @returns {Transaction}
*/
fromRestObject(obj) {
const t = new Transaction(null, null);
const tsConverter = new TransactionSettingsConverter();
t.id = obj.id;
t.initiator = obj.initiator;
t.phase = obj.phase;
t.timestamp = obj.timestamp;
t.result = obj.result;
t.buySettings = tsConverter.fromRestObject(obj.buySettings);
t.sellSettings = tsConverter.fromRestObject(obj.sellSettings);
t.symbol = TradingPairs.fromString(obj.symbol);
return t;
}
}

View File

@ -0,0 +1,41 @@
import TransactionSettings from "../../../apiwrapper/transaction/TransactionSettings.js";
import AbstractConverter from "../AbstractConverter.js";
import ConverterFactory from "../ConverterFactory.js";
export default class TransactionSettingsConverter extends AbstractConverter {
constructor(){
super();
}
/**
* @param {TransactionSettings} obj
* @returns {object}
*/
toRestObject(obj) {
return {
_objectType: ConverterFactory.OBJECT_TYPE_TRANSACTION_SETTINGS,
id: obj.apiID,
orderPrice: obj.orderPrice,
orderQuantity: obj.orderQuantity,
price: obj.price,
quantity: obj.quantity
};
}
/**
* @param {object} obj
* @returns {TransactionSettings}
*/
fromRestObject(obj) {
const ts = new TransactionSettings(null, null);
ts.apiID = obj.id;
ts.orderPrice = obj.orderPrice;
ts.orderQuantity = obj.orderQuantity;
ts.price = obj.price;
ts.quantity = obj.quantity;
return ts;
}
}