[BOT] implement buy und sell propagating from worker to api
This commit is contained in:
parent
adbe4f30c8
commit
ed9ca77def
@ -16,6 +16,7 @@ import Transaction from "../../apiwrapper/transaction/Transaction.js";
|
||||
import TransactionUpdateEvent from "../../apiwrapper/event/TransactionUpdateEvent.js";
|
||||
import TransactionFill from "../../apiwrapper/transaction/TransactionFill.js";
|
||||
import TransactionStatus from "../../apiwrapper/transaction/TransactionStatus.js";
|
||||
import TransactionPhase from "../../apiwrapper/transaction/TransactionPhase.js";
|
||||
|
||||
export default class BinanceApiClient extends APIClient {
|
||||
/**
|
||||
@ -266,6 +267,7 @@ export default class BinanceApiClient extends APIClient {
|
||||
"timestamp": Date.now()
|
||||
}).then(resp => {
|
||||
transaction.buySettings.apiID = resp.orderId;
|
||||
transaction.phase = TransactionPhase.BUY_IN_PROGRESS;
|
||||
}).catch(e => {
|
||||
this.getLogger().error("Unable to create buy order for " + transaction.id, {code: e.code, msg: e.message, url: e.requestUrl});
|
||||
const event = new TransactionUpdateEvent(transaction.id, transaction.buySettings.apiID, TransactionStatus.CANCELED)
|
||||
@ -288,6 +290,7 @@ export default class BinanceApiClient extends APIClient {
|
||||
"timestamp": Date.now()
|
||||
}).then(resp => {
|
||||
transaction.sellSettings.apiID = resp.orderId;
|
||||
transaction.phase = TransactionPhase.SELL_IN_PROGRESS;
|
||||
}).catch(e => {
|
||||
this.getLogger().error("Unable to create sell order for " + transaction.id, {code: e.code, msg: e.message, url: e.requestUrl});
|
||||
const event = new TransactionUpdateEvent(transaction.id, transaction.sellSettings.apiID, TransactionStatus.CANCELED)
|
||||
|
||||
@ -45,6 +45,10 @@ export default class Transaction extends Serializable {
|
||||
*/
|
||||
timestamp = 0;
|
||||
|
||||
/**
|
||||
* @param {string} initiator
|
||||
* @param {TradingPair} tradingPair
|
||||
*/
|
||||
constructor(initiator, tradingPair){
|
||||
super();
|
||||
this.initiator = initiator;
|
||||
|
||||
@ -123,7 +123,7 @@ export default class TradingBot {
|
||||
this.#loadWorker();
|
||||
this.#worker.forEach(worker => {
|
||||
this.#registerTradingPair(worker.getTradingPair());
|
||||
worker.init(this.#logger, this.#config.getDataDirectory());
|
||||
worker.init(this.#logger, this.#config.getDataDirectory(), this);
|
||||
});
|
||||
this.#transactions.forEach(transaction => {
|
||||
const type = transaction.phase === (TransactionPhase.INITIAL || transaction.phase === TransactionPhase.BUY_IN_PROGRESS) ? "buy" : "sell";
|
||||
@ -235,6 +235,7 @@ export default class TradingBot {
|
||||
handleAccountUpdate(accountUpdateEvent) {
|
||||
switch (accountUpdateEvent.eventType) {
|
||||
case APIEventType.BALANCE_CHANGE:
|
||||
this.#logger.info("Balance update: ", accountUpdateEvent);
|
||||
// TODO update changed balances
|
||||
break;
|
||||
case APIEventType.TRANSACTION_UPDATE:
|
||||
@ -337,6 +338,41 @@ export default class TradingBot {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {number} quantity
|
||||
* @param {number} price
|
||||
*/
|
||||
requestBuy(worker, quantity, price){
|
||||
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.orderQuantity = Math.round(this.#config.getPerTradeLimit() / price);
|
||||
this.#transactions.push(transaction);
|
||||
this.#saveTransactions();
|
||||
|
||||
this.#api.requestBuy(transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
requestSell(worker, transaction){
|
||||
this.#api.requestSell(transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
requestCancle(worker, transaction){
|
||||
// not implemented as this class is only an interface!
|
||||
}
|
||||
|
||||
#loadTransactions() {
|
||||
try {
|
||||
this.#transactions = SerializableHelper.load(this.#config.getDataDirectory(), 'transactions.sjson', Transaction);
|
||||
@ -351,7 +387,7 @@ export default class TradingBot {
|
||||
}
|
||||
}
|
||||
|
||||
#saveTransactions() {
|
||||
async #saveTransactions() {
|
||||
SerializableHelper.save(this.#config.getDataDirectory(), 'transactions.sjson', this.#transactions);
|
||||
SerializableHelper.save(this.#config.getDataDirectory(), 'transactionHistory.sjson', this.#transactionHistory);
|
||||
}
|
||||
@ -366,7 +402,7 @@ export default class TradingBot {
|
||||
}
|
||||
}
|
||||
|
||||
#saveWorker() {
|
||||
async #saveWorker() {
|
||||
const workerArr = [];
|
||||
Array.from(this.#worker.values()).forEach(w => workerArr.push(w));
|
||||
SerializableHelper.save(this.#config.getDataDirectory(), 'worker.sjson', workerArr);
|
||||
|
||||
@ -5,6 +5,7 @@ import Serializable from "../../util/Serializable.js";
|
||||
import SerializableHelper from "../../util/SerializableHelper.js";
|
||||
import AssetData from "../data/asset/AssetData.js";
|
||||
import AbstractStrategy from "../strategy/AbstractStrategy.js";
|
||||
import WorkerTradingApiProvider from "./WorkerTradingApiProvider.js";
|
||||
|
||||
export default class AbstractWorker extends Serializable {
|
||||
|
||||
@ -28,6 +29,11 @@ export default class AbstractWorker extends Serializable {
|
||||
*/
|
||||
#strategy = null;
|
||||
|
||||
/**
|
||||
* @type {WorkerTradingApiProvider}
|
||||
*/
|
||||
#apiProvider = null
|
||||
|
||||
/**
|
||||
* @type {Logger}
|
||||
*/
|
||||
@ -49,9 +55,11 @@ export default class AbstractWorker extends Serializable {
|
||||
/**
|
||||
* @param {Logger} logger
|
||||
* @param {string} dataPath
|
||||
* @param {WorkerTradingApiProvider} apiProvider
|
||||
*/
|
||||
init(logger, dataPath){
|
||||
init(logger, dataPath, apiProvider){
|
||||
this.#logger = logger;
|
||||
this.#apiProvider = apiProvider;
|
||||
if(this.#strategy != null){
|
||||
this.#strategy.init(logger);
|
||||
}
|
||||
@ -114,6 +122,13 @@ export default class AbstractWorker extends Serializable {
|
||||
return this.#logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {WorkerTradingApiProvider}
|
||||
*/
|
||||
getApiProvider(){
|
||||
return this.#apiProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} dataPath path to data directory
|
||||
*/
|
||||
|
||||
@ -28,16 +28,17 @@ export default class DefaultWorker extends AbstractWorker{
|
||||
*/
|
||||
onUpdate(assetData, transactions){
|
||||
this.getStrategy().updateAssetData(assetData);
|
||||
const price = this.getStrategy().getAssetData().getOrderBook().getBestBid().price;
|
||||
|
||||
if(this.getStrategy().shouldBuy()){
|
||||
// TODO create transaction!
|
||||
this.getApiProvider().requestBuy(this, Math.round(50 / price), price);
|
||||
}
|
||||
|
||||
for(let transaction of transactions){
|
||||
if(transaction.phase == TransactionPhase.BUY_DONE && this.getStrategy().shouldSell(transaction)){
|
||||
// TODO request sell!
|
||||
this.getApiProvider().requestSell(this, transaction);
|
||||
} else if(this.getStrategy().shouldCancle()){
|
||||
// TODO request cancle
|
||||
this.getApiProvider().requestCancle(this, transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
src/js/tradingbot/worker/WorkerTradingApiProvider.js
Normal file
29
src/js/tradingbot/worker/WorkerTradingApiProvider.js
Normal file
@ -0,0 +1,29 @@
|
||||
import Transaction from "../../apiwrapper/transaction/Transaction.js";
|
||||
import AbstractWorker from "./AbstractWorker.js";
|
||||
|
||||
export default class WorkerTradingApiProvider {
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {number} quantity
|
||||
* @param {number} price
|
||||
*/
|
||||
requestBuy(worker, quantity, price){
|
||||
// not implemented as this class is only an interface!
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
requestSell(worker, transaction){
|
||||
// not implemented as this class is only an interface!
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractWorker} worker
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
requestCancle(worker, transaction){
|
||||
// not implemented as this class is only an interface!
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user