[#21] Bug fixes and rest service and point for aggregated data
This commit is contained in:
parent
1085c58ebc
commit
69a548a200
@ -1,6 +1,7 @@
|
||||
import TradingPairs from "../apiwrapper/assets/TraidingPairs.js";
|
||||
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
||||
import WebViewDataProvider from "../webview/WebViewDataProvider.js";
|
||||
import AssetData from "./data/asset/AssetData.js";
|
||||
import TradingBot from "./TradingBot.js";
|
||||
|
||||
export default class TradingBotRestDataProvider extends WebViewDataProvider {
|
||||
@ -29,7 +30,15 @@ export default class TradingBotRestDataProvider extends WebViewDataProvider {
|
||||
* @returns {OrderBook}
|
||||
*/
|
||||
getOrderBook(symbol) {
|
||||
return this.#tradingBot.getAssetDataCollector().getAssetData(symbol).getOrderBook();
|
||||
return this.getAssetData(symbol).getOrderBook();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} symbol
|
||||
* @returns {AssetData}
|
||||
*/
|
||||
getAssetData(symbol){
|
||||
return this.#tradingBot.getAssetDataCollector().getAssetData(symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import TradeEvent from "../../../apiwrapper/event/TradeEvent.js";
|
||||
import OrderBookEntry from "../../../apiwrapper/orderbook/OrderBookEntry.js";
|
||||
|
||||
export default class AggregatedDataPoint {
|
||||
@ -61,12 +60,12 @@ export default class AggregatedDataPoint {
|
||||
/**
|
||||
* @type {OrderBookEntry}
|
||||
*/
|
||||
bestAsk = 0;
|
||||
bestAsk = null;
|
||||
|
||||
/**
|
||||
* @type {OrderBookEntry}
|
||||
*/
|
||||
bestBid = 0;
|
||||
bestBid = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
@ -107,12 +106,14 @@ export default class AggregatedDataPoint {
|
||||
pushBid(bid){
|
||||
if(!this.hasValues){
|
||||
this.startPrice = bid.price;
|
||||
this.minPrice = bid.price;
|
||||
this.maxPrice = bid.price;
|
||||
}
|
||||
this.hasValues = true;
|
||||
this.minPrice = Math.min(this.minPrice, bid.price);
|
||||
this.maxPrice = Math.max(this.maxPrice = bid.price);
|
||||
this.endPrice = bid.price;
|
||||
this.#priceValues.push(bid.price);
|
||||
this.#priceValues.push(parseFloat(bid.price));
|
||||
if(this.bestBid == null || this.bestBid.price < bid.price){
|
||||
this.bestBid = bid;
|
||||
}
|
||||
@ -148,6 +149,9 @@ export default class AggregatedDataPoint {
|
||||
this.#priceValues = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {AggregatedDataPoint} returns a deep copy of this object
|
||||
*/
|
||||
clone(){
|
||||
const dp = new AggregatedDataPoint(this.startTime, this.duration);
|
||||
dp.startPrice = this.startPrice;
|
||||
@ -163,5 +167,7 @@ export default class AggregatedDataPoint {
|
||||
dp.tradeVolume = this.tradeVolume;
|
||||
dp.bestAsk = this.bestAsk;
|
||||
dp.bestBid = this.bestBid;
|
||||
|
||||
return dp;
|
||||
}
|
||||
}
|
||||
@ -47,7 +47,7 @@ export default class AssetDataAggregator {
|
||||
|
||||
const tmpSlot = new AggregatedDataPoint(timestamp - AssetDataAggregator.#SLOT_1_MIN, AssetDataAggregator.#SLOT_1_MIN);
|
||||
|
||||
for(let i = this.#perSecondDataPoints.length - 60; i >= 0; i--){
|
||||
for(let i = this.#perSecondDataPoints.length - 60; i < this.#perSecondDataPoints.length; i++){
|
||||
const dp = this.#perSecondDataPoints[i];
|
||||
tmpSlot.pushAsk(dp.bestAsk);
|
||||
tmpSlot.pushBid(dp.bestBid);
|
||||
@ -71,10 +71,13 @@ export default class AssetDataAggregator {
|
||||
return;
|
||||
}
|
||||
|
||||
const tmpSlot = this.#currentDataPoint;
|
||||
let tmpSlot = this.#currentDataPoint;
|
||||
if(!tmpSlot.hasValues){
|
||||
tmpSlot = this.#perSecondDataPoints[this.#perSecondDataPoints.length - 1].clone();
|
||||
tmpSlot.startTime = timestamp - AssetDataAggregator.#SLOT_1_SEC;
|
||||
tmpSlot.endTime = timestamp;
|
||||
tmpSlot.tradeCount = 0;
|
||||
tmpSlot.tradeVolume = 0;
|
||||
}
|
||||
this.#currentDataPoint = new AggregatedDataPoint(timestamp, AssetDataAggregator.#SLOT_1_SEC);
|
||||
tmpSlot.end(timestamp);
|
||||
@ -102,6 +105,8 @@ export default class AssetDataAggregator {
|
||||
const newPoint = point.clone();
|
||||
newPoint.startTime = point.startTime + duration * (i + 1);
|
||||
newPoint.endTime = newPoint.startTime + duration;
|
||||
newPoint.tradeCount = 0;
|
||||
newPoint.tradeVolume = 0;
|
||||
targetArr.push(newPoint);
|
||||
}
|
||||
}
|
||||
@ -119,7 +124,7 @@ export default class AssetDataAggregator {
|
||||
* @returns {AggregatedDataPoint[]}
|
||||
*/
|
||||
getData(duration, start = -1){
|
||||
const result = [];
|
||||
let result = [];
|
||||
const durationInMs = UnitHelper.formatedDurationToMs(duration);
|
||||
|
||||
// if seconds data required
|
||||
@ -132,7 +137,7 @@ export default class AssetDataAggregator {
|
||||
const dpCount = Math.round(durationInMs / AssetDataAggregator.#SLOT_1_MIN);
|
||||
const pointOffset = start == -1 ? 0 : Math.round(start / AssetDataAggregator.#SLOT_1_MIN);
|
||||
if(pointOffset + dpCount <= this.#perMinuteDataPoints.length){
|
||||
result = this.#perMinuteDataPoints.slice(-1 * (pointOffset + dpCount), -1 * pointOffset);
|
||||
result = this.#perMinuteDataPoints.slice(-1 * (pointOffset + dpCount), pointOffset > 0 ? -1 * pointOffset : this.#perMinuteDataPoints.length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ export default class UnitHelper {
|
||||
if (match) {
|
||||
return match[1] * UnitHelper.#CHRONO_UNIT_TO_MS_MAPPING.get(match[2]);
|
||||
} else {
|
||||
return 0;
|
||||
return isNaN(duration) ? 0 : parseFloat(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ import bodyParser from "body-parser";
|
||||
import cors from "cors";
|
||||
import WebViewDataProvider from "./WebViewDataProvider.js";
|
||||
import ConverterFactory from "./converter/ConverterFactory.js";
|
||||
import AggregatedDataPointConverter from "./converter/converters/AggregatedDataPointConverter.js";
|
||||
|
||||
export default class RestClient {
|
||||
|
||||
@ -63,6 +64,10 @@ export default class RestClient {
|
||||
res.json(this.#getAssetOrderBook(req.params.symbol));
|
||||
});
|
||||
|
||||
this.#service.get("/asset/:symbol/aggregated", (req, res, next) => {
|
||||
res.json(this.#getAggregatedAssetData(req.params.symbol, req.query.startTime, req.query.duration));
|
||||
});
|
||||
|
||||
this.#service.get("/worker/:name/attribute/:attr", (req, res, next) => {
|
||||
res.json(this.#getWorkerAttribute(req.params.name, req.params.attr));
|
||||
});
|
||||
@ -76,6 +81,19 @@ export default class RestClient {
|
||||
|
||||
}
|
||||
|
||||
#getAggregatedAssetData(asset, starttime, duration){
|
||||
const st = starttime != null ? starttime : -1;
|
||||
const d = duration != null ? duration : 3600000;
|
||||
|
||||
const data = this.#dataProvider.getAssetData(asset).assetDataAggregator.getData(d, st);
|
||||
const converter = new AggregatedDataPointConverter();
|
||||
const result = [];
|
||||
|
||||
data.forEach(dp => result.push(converter.toRestObject(dp)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#getAssetOrderBook(asset){
|
||||
const orderBook = this.#dataProvider.getOrderBook(asset);
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import OrderBook from "../apiwrapper/orderbook/OrderBook.js";
|
||||
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
||||
import AssetData from "../tradingbot/data/asset/AssetData.js";
|
||||
import AbstractWorker from "../tradingbot/worker/AbstractWorker.js";
|
||||
|
||||
export default class WebViewDataProvider {
|
||||
@ -54,4 +55,12 @@ export default class WebViewDataProvider {
|
||||
getWorkers(){
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} symbol
|
||||
* @returns {AssetData}
|
||||
*/
|
||||
getAssetData(symbol){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,15 @@
|
||||
import OrderBook from "../../apiwrapper/orderbook/OrderBook.js";
|
||||
import OrderBookEntry from "../../apiwrapper/orderbook/OrderBookEntry.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";
|
||||
|
||||
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';
|
||||
|
||||
/**
|
||||
* @param {any} obj
|
||||
@ -25,6 +28,8 @@ export default class ConverterFactory {
|
||||
return new OrderBookConverter();
|
||||
} else if (obj instanceof OrderBookEntry) {
|
||||
return new OrderBookEntryConverter();
|
||||
} else if (obj instanceof AggregatedDataPoint){
|
||||
return new AggregatedDataPointConverter();
|
||||
}
|
||||
|
||||
throw new Error("No converter defined for: " + JSON.stringify(obj));
|
||||
@ -40,6 +45,8 @@ export default class ConverterFactory {
|
||||
return new OrderBookConverter();
|
||||
case this.OBJECT_TYPE_ORDER_BOOK_ENTRY:
|
||||
return new OrderBookEntryConverter();
|
||||
case this.OBJECT_TYPE_AGGREGATED_DATA_POINT:
|
||||
return new AggregatedDataPointConverter();
|
||||
default:
|
||||
throw new Error("No converter defined for type: " + type);
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
import AggregatedDataPoint from "../../../tradingbot/data/asset/AggregatedDataPoint.js";
|
||||
import AbstractConverter from "../AbstractConverter.js";
|
||||
import ConverterFactory from "../ConverterFactory.js";
|
||||
import OrderBookEntryConverter from "./OrderBookEntryConverter.js";
|
||||
|
||||
export default class AggregatedDataPointConverter extends AbstractConverter {
|
||||
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AggregatedDataPoint} obj
|
||||
* @returns {object}
|
||||
*/
|
||||
toRestObject(obj) {
|
||||
const obeConverter = new OrderBookEntryConverter();
|
||||
return {
|
||||
_objectType: ConverterFactory.OBJECT_TYPE_AGGREGATED_DATA_POINT,
|
||||
startTime: obj.startTime,
|
||||
endTime: obj.endTime,
|
||||
duration: obj.duration,
|
||||
tradeCount: obj.tradeCount,
|
||||
tradeVolume: obj.tradeVolume,
|
||||
minPrice: obj.minPrice,
|
||||
maxPrice: obj.maxPrice,
|
||||
avgPrice: obj.avgPrice,
|
||||
startPrice: obj.startPrice,
|
||||
endPrice: obj.endPrice,
|
||||
bestAsk: obeConverter.toRestObject(obj.bestAsk),
|
||||
bestBid: obeConverter.toRestObject(obj.bestBid),
|
||||
peakStarts: obj.peakStarts,
|
||||
peakEnds: obj.peakEnds
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} obj
|
||||
* @returns {AggregatedDataPoint}
|
||||
*/
|
||||
fromRestObject(obj) {
|
||||
const obeConverter = new OrderBookEntryConverter();
|
||||
const dp = new AggregatedDataPoint(obj.startTime, obj.duration);
|
||||
|
||||
dp.startTime = obj.startTime;
|
||||
dp.endTime = obj.endTime;
|
||||
dp.duration = obj.duration;
|
||||
dp.tradeCount = obj.tradeCount;
|
||||
dp.tradeVolume = obj.tradeVolume;
|
||||
dp.minPrice = obj.minPrice;
|
||||
dp.maxPrice = obj.maxPrice;
|
||||
dp.avgPrice = obj.avgPrice;
|
||||
dp.startPrice = obj.startPrice;
|
||||
dp.endPrice = obj.endPrice;
|
||||
dp.bestAsk = obeConverter.fromRestObject(obj.bestAsk);
|
||||
dp.bestBid = obeConverter.fromRestObject(obj.bestBid);
|
||||
dp.peakStarts = obj.peakStarts;
|
||||
dp.peakEnds = obj.peakEnds;
|
||||
|
||||
return dp;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user