Compare commits
2 Commits
1085c58ebc
...
e002eeec44
| Author | SHA1 | Date | |
|---|---|---|---|
| e002eeec44 | |||
| 69a548a200 |
@ -1,6 +1,7 @@
|
|||||||
import TradingPairs from "../apiwrapper/assets/TraidingPairs.js";
|
import TradingPairs from "../apiwrapper/assets/TraidingPairs.js";
|
||||||
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
||||||
import WebViewDataProvider from "../webview/WebViewDataProvider.js";
|
import WebViewDataProvider from "../webview/WebViewDataProvider.js";
|
||||||
|
import AssetData from "./data/asset/AssetData.js";
|
||||||
import TradingBot from "./TradingBot.js";
|
import TradingBot from "./TradingBot.js";
|
||||||
|
|
||||||
export default class TradingBotRestDataProvider extends WebViewDataProvider {
|
export default class TradingBotRestDataProvider extends WebViewDataProvider {
|
||||||
@ -29,7 +30,15 @@ export default class TradingBotRestDataProvider extends WebViewDataProvider {
|
|||||||
* @returns {OrderBook}
|
* @returns {OrderBook}
|
||||||
*/
|
*/
|
||||||
getOrderBook(symbol) {
|
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";
|
import OrderBookEntry from "../../../apiwrapper/orderbook/OrderBookEntry.js";
|
||||||
|
|
||||||
export default class AggregatedDataPoint {
|
export default class AggregatedDataPoint {
|
||||||
@ -61,12 +60,12 @@ export default class AggregatedDataPoint {
|
|||||||
/**
|
/**
|
||||||
* @type {OrderBookEntry}
|
* @type {OrderBookEntry}
|
||||||
*/
|
*/
|
||||||
bestAsk = 0;
|
bestAsk = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {OrderBookEntry}
|
* @type {OrderBookEntry}
|
||||||
*/
|
*/
|
||||||
bestBid = 0;
|
bestBid = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@ -107,12 +106,14 @@ export default class AggregatedDataPoint {
|
|||||||
pushBid(bid){
|
pushBid(bid){
|
||||||
if(!this.hasValues){
|
if(!this.hasValues){
|
||||||
this.startPrice = bid.price;
|
this.startPrice = bid.price;
|
||||||
|
this.minPrice = bid.price;
|
||||||
|
this.maxPrice = bid.price;
|
||||||
}
|
}
|
||||||
this.hasValues = true;
|
this.hasValues = true;
|
||||||
this.minPrice = Math.min(this.minPrice, bid.price);
|
this.minPrice = Math.min(this.minPrice, bid.price);
|
||||||
this.maxPrice = Math.max(this.maxPrice = bid.price);
|
this.maxPrice = Math.max(this.maxPrice, bid.price);
|
||||||
this.endPrice = 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){
|
if(this.bestBid == null || this.bestBid.price < bid.price){
|
||||||
this.bestBid = bid;
|
this.bestBid = bid;
|
||||||
}
|
}
|
||||||
@ -142,12 +143,18 @@ export default class AggregatedDataPoint {
|
|||||||
*/
|
*/
|
||||||
end(endTime){
|
end(endTime){
|
||||||
this.endTime = endTime;
|
this.endTime = endTime;
|
||||||
|
if(this.#priceValues.length > 0){
|
||||||
let priceSum = 0;
|
let priceSum = 0;
|
||||||
this.#priceValues.forEach(p => priceSum += p);
|
this.#priceValues.forEach(p => priceSum += p);
|
||||||
this.avgPrice = priceSum / this.#priceValues.length;
|
this.avgPrice = priceSum / this.#priceValues.length;
|
||||||
|
}
|
||||||
|
console.log(this.minPrice, this.maxPrice, this.avgPrice, this.minPrice <= this.avgPrice, this.avgPrice <= this.maxPrice);
|
||||||
this.#priceValues = [];
|
this.#priceValues = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {AggregatedDataPoint} returns a deep copy of this object
|
||||||
|
*/
|
||||||
clone(){
|
clone(){
|
||||||
const dp = new AggregatedDataPoint(this.startTime, this.duration);
|
const dp = new AggregatedDataPoint(this.startTime, this.duration);
|
||||||
dp.startPrice = this.startPrice;
|
dp.startPrice = this.startPrice;
|
||||||
@ -163,5 +170,7 @@ export default class AggregatedDataPoint {
|
|||||||
dp.tradeVolume = this.tradeVolume;
|
dp.tradeVolume = this.tradeVolume;
|
||||||
dp.bestAsk = this.bestAsk;
|
dp.bestAsk = this.bestAsk;
|
||||||
dp.bestBid = this.bestBid;
|
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);
|
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];
|
const dp = this.#perSecondDataPoints[i];
|
||||||
tmpSlot.pushAsk(dp.bestAsk);
|
tmpSlot.pushAsk(dp.bestAsk);
|
||||||
tmpSlot.pushBid(dp.bestBid);
|
tmpSlot.pushBid(dp.bestBid);
|
||||||
@ -71,10 +71,13 @@ export default class AssetDataAggregator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tmpSlot = this.#currentDataPoint;
|
let tmpSlot = this.#currentDataPoint;
|
||||||
if(!tmpSlot.hasValues){
|
if(!tmpSlot.hasValues){
|
||||||
tmpSlot = this.#perSecondDataPoints[this.#perSecondDataPoints.length - 1].clone();
|
tmpSlot = this.#perSecondDataPoints[this.#perSecondDataPoints.length - 1].clone();
|
||||||
tmpSlot.startTime = timestamp - AssetDataAggregator.#SLOT_1_SEC;
|
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);
|
this.#currentDataPoint = new AggregatedDataPoint(timestamp, AssetDataAggregator.#SLOT_1_SEC);
|
||||||
tmpSlot.end(timestamp);
|
tmpSlot.end(timestamp);
|
||||||
@ -102,6 +105,8 @@ export default class AssetDataAggregator {
|
|||||||
const newPoint = point.clone();
|
const newPoint = point.clone();
|
||||||
newPoint.startTime = point.startTime + duration * (i + 1);
|
newPoint.startTime = point.startTime + duration * (i + 1);
|
||||||
newPoint.endTime = newPoint.startTime + duration;
|
newPoint.endTime = newPoint.startTime + duration;
|
||||||
|
newPoint.tradeCount = 0;
|
||||||
|
newPoint.tradeVolume = 0;
|
||||||
targetArr.push(newPoint);
|
targetArr.push(newPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +124,7 @@ export default class AssetDataAggregator {
|
|||||||
* @returns {AggregatedDataPoint[]}
|
* @returns {AggregatedDataPoint[]}
|
||||||
*/
|
*/
|
||||||
getData(duration, start = -1){
|
getData(duration, start = -1){
|
||||||
const result = [];
|
let result = [];
|
||||||
const durationInMs = UnitHelper.formatedDurationToMs(duration);
|
const durationInMs = UnitHelper.formatedDurationToMs(duration);
|
||||||
|
|
||||||
// if seconds data required
|
// if seconds data required
|
||||||
@ -132,7 +137,7 @@ export default class AssetDataAggregator {
|
|||||||
const dpCount = Math.round(durationInMs / AssetDataAggregator.#SLOT_1_MIN);
|
const dpCount = Math.round(durationInMs / AssetDataAggregator.#SLOT_1_MIN);
|
||||||
const pointOffset = start == -1 ? 0 : Math.round(start / AssetDataAggregator.#SLOT_1_MIN);
|
const pointOffset = start == -1 ? 0 : Math.round(start / AssetDataAggregator.#SLOT_1_MIN);
|
||||||
if(pointOffset + dpCount <= this.#perMinuteDataPoints.length){
|
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) {
|
if (match) {
|
||||||
return match[1] * UnitHelper.#CHRONO_UNIT_TO_MS_MAPPING.get(match[2]);
|
return match[1] * UnitHelper.#CHRONO_UNIT_TO_MS_MAPPING.get(match[2]);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return isNaN(duration) ? 0 : parseFloat(duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ import bodyParser from "body-parser";
|
|||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import WebViewDataProvider from "./WebViewDataProvider.js";
|
import WebViewDataProvider from "./WebViewDataProvider.js";
|
||||||
import ConverterFactory from "./converter/ConverterFactory.js";
|
import ConverterFactory from "./converter/ConverterFactory.js";
|
||||||
|
import AggregatedDataPointConverter from "./converter/converters/AggregatedDataPointConverter.js";
|
||||||
|
|
||||||
export default class RestClient {
|
export default class RestClient {
|
||||||
|
|
||||||
@ -63,6 +64,10 @@ export default class RestClient {
|
|||||||
res.json(this.#getAssetOrderBook(req.params.symbol));
|
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) => {
|
this.#service.get("/worker/:name/attribute/:attr", (req, res, next) => {
|
||||||
res.json(this.#getWorkerAttribute(req.params.name, req.params.attr));
|
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){
|
#getAssetOrderBook(asset){
|
||||||
const orderBook = this.#dataProvider.getOrderBook(asset);
|
const orderBook = this.#dataProvider.getOrderBook(asset);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import OrderBook from "../apiwrapper/orderbook/OrderBook.js";
|
import OrderBook from "../apiwrapper/orderbook/OrderBook.js";
|
||||||
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
import Transaction from "../apiwrapper/transaction/Transaction.js";
|
||||||
|
import AssetData from "../tradingbot/data/asset/AssetData.js";
|
||||||
import AbstractWorker from "../tradingbot/worker/AbstractWorker.js";
|
import AbstractWorker from "../tradingbot/worker/AbstractWorker.js";
|
||||||
|
|
||||||
export default class WebViewDataProvider {
|
export default class WebViewDataProvider {
|
||||||
@ -54,4 +55,12 @@ export default class WebViewDataProvider {
|
|||||||
getWorkers(){
|
getWorkers(){
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} symbol
|
||||||
|
* @returns {AssetData}
|
||||||
|
*/
|
||||||
|
getAssetData(symbol){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,12 +1,15 @@
|
|||||||
import OrderBook from "../../apiwrapper/orderbook/OrderBook.js";
|
import OrderBook from "../../apiwrapper/orderbook/OrderBook.js";
|
||||||
import OrderBookEntry from "../../apiwrapper/orderbook/OrderBookEntry.js";
|
import OrderBookEntry from "../../apiwrapper/orderbook/OrderBookEntry.js";
|
||||||
|
import AggregatedDataPoint from "../../tradingbot/data/asset/AggregatedDataPoint.js";
|
||||||
import AbstractConverter from "./AbstractConverter.js";
|
import AbstractConverter from "./AbstractConverter.js";
|
||||||
|
import AggregatedDataPointConverter from "./converters/AggregatedDataPointConverter.js";
|
||||||
import OrderBookConverter from "./converters/OrderBookConverter.js";
|
import OrderBookConverter from "./converters/OrderBookConverter.js";
|
||||||
import OrderBookEntryConverter from "./converters/OrderBookEntryConverter.js";
|
import OrderBookEntryConverter from "./converters/OrderBookEntryConverter.js";
|
||||||
|
|
||||||
export default class ConverterFactory {
|
export default class ConverterFactory {
|
||||||
static OBJECT_TYPE_ORDER_BOOK = 'order_book';
|
static OBJECT_TYPE_ORDER_BOOK = 'order_book';
|
||||||
static OBJECT_TYPE_ORDER_BOOK_ENTRY = 'order_book_entry';
|
static OBJECT_TYPE_ORDER_BOOK_ENTRY = 'order_book_entry';
|
||||||
|
static OBJECT_TYPE_AGGREGATED_DATA_POINT = 'aggregated_data_point';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} obj
|
* @param {any} obj
|
||||||
@ -25,6 +28,8 @@ export default class ConverterFactory {
|
|||||||
return new OrderBookConverter();
|
return new OrderBookConverter();
|
||||||
} else if (obj instanceof OrderBookEntry) {
|
} else if (obj instanceof OrderBookEntry) {
|
||||||
return new OrderBookEntryConverter();
|
return new OrderBookEntryConverter();
|
||||||
|
} else if (obj instanceof AggregatedDataPoint){
|
||||||
|
return new AggregatedDataPointConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("No converter defined for: " + JSON.stringify(obj));
|
throw new Error("No converter defined for: " + JSON.stringify(obj));
|
||||||
@ -40,6 +45,8 @@ export default class ConverterFactory {
|
|||||||
return new OrderBookConverter();
|
return new OrderBookConverter();
|
||||||
case this.OBJECT_TYPE_ORDER_BOOK_ENTRY:
|
case this.OBJECT_TYPE_ORDER_BOOK_ENTRY:
|
||||||
return new OrderBookEntryConverter();
|
return new OrderBookEntryConverter();
|
||||||
|
case this.OBJECT_TYPE_AGGREGATED_DATA_POINT:
|
||||||
|
return new AggregatedDataPointConverter();
|
||||||
default:
|
default:
|
||||||
throw new Error("No converter defined for type: " + type);
|
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