Skip to content

Commit

Permalink
fixed candle maker duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
Ekliptor authored and Ekliptor committed Mar 29, 2020
1 parent a981566 commit 1fdcd42
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
22 changes: 22 additions & 0 deletions config/CandleTester.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": [
{
"exchanges": [
"Bitfinex"
],
"marginTrading": true,
"tradeTotalBtc": 0,
"warmUpMin": 0,
"updateIndicatorsOnTrade": false,
"flipPosition": false,
"closePositionFirst": false,
"strategies": {
"CandleTester": {
"pair": "USD_BTC",
"candleSize": 1,
"enableLog": true
}
}
}
]
}
1 change: 0 additions & 1 deletion config/FishingNet.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"fishingMode": "trend",
"percentage": 15.0,
"maxPosIncreases": 7,
"scaleOutPerc": 0.0,
"tradingAmountIncreaseFactor": 1.1,
"profitPercent": 4.1,
"interval": 24,
Expand Down
1 change: 1 addition & 0 deletions imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "./src/Strategies/BollingerDayTrader";
import "./src/Strategies/BollingerStop";
import "./src/Strategies/BreakoutDetector";
import "./src/Strategies/CandleRepeater";
import "./src/Strategies/CandleTester";
import "./src/Strategies/ChannelBreakout";
import "./src/Strategies/CurrencyPairArbitrage";
import "./src/Strategies/DayTrader";
Expand Down
46 changes: 46 additions & 0 deletions src/Strategies/CandleTester.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as utils from "@ekliptor/apputils";
const logger = utils.logger
, nconf = utils.nconf;
import {AbstractStrategy, StrategyAction} from "./AbstractStrategy";
import {TechnicalStrategy, TechnicalStrategyAction} from "./TechnicalStrategy";
import {AbstractIndicator} from "../Indicators/AbstractIndicator";
import {Currency, Trade, Candle} from "@ekliptor/bit-models";

interface CandleTesterAction extends TechnicalStrategyAction {
sample: string;
}

/**
* This strategy just logs candles.
* It is only intended for debugging purposes.
*/
export default class CandleTester extends TechnicalStrategy {
public action: CandleTesterAction;
protected candleTickCounter: number = 0; // counts the number of candles after start — need for valid calculations with kama


constructor(options) {
super(options)
this.addInfoFunction("sample", () => {
return this.action.sample;
});
}

public getMinWarumCandles() {
return 0; // ensure we don't start any trade imports with this strategy
}

// ################################################################
// ###################### PRIVATE FUNCTIONS #######################
protected async candleTick(candle: Candle.Candle): Promise<void> {
this.candleTickCounter += 1;
logger.verbose("%s candle: %s CandleTester Market time: %s",
this.candleTickCounter, utils.getUnixTimeStr(true, candle.start), utils.getUnixTimeStr(true, this.marketTime));

return super.candleTick(candle);
}

protected checkIndicators() {
// this strategy does nothing
}
}
27 changes: 23 additions & 4 deletions src/Trade/Candles/CandleMaker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ export class CandleMaker<T extends TradeBase> extends CandleStream<T> {
this.fillBuckets(trades);
let candles = this.calculateCandles();

candles = this.addEmptyCandles(candles, previousEndTime);
// find the max date where we stopped emitting to know where to start filling empty candle gaps (if there are no trades)
let maxDate = previousEndTime;
if (maxDate) {
if (this.threshold && this.threshold.getTime() > previousEndTime.getTime())
maxDate = this.threshold;
if (maxDate && this.lastCandleMinute >= 0) {
let lastEmitDate = new Date(maxDate); // copy
lastEmitDate.setUTCMinutes(this.lastCandleMinute+1); // increment to ensure we don't send the same
if (lastEmitDate.getTime() > maxDate.getTime())
maxDate = previousEndTime;
}
}
candles = this.addEmptyCandles(candles, maxDate);

// the last candle is not complete, don't emit it & keep it in here (in buckets)
let last = candles.pop();
Expand Down Expand Up @@ -103,13 +115,15 @@ export class CandleMaker<T extends TradeBase> extends CandleStream<T> {
return;
const latestCandle = candles[candles.length-1];
if (this.lastCandleMinute === latestCandle.start.getUTCMinutes()) {
logger.warn("Skipped emitting another candle for minute %s, last %s", this.lastCandleMinute, utils.date.toDateTimeStr(latestCandle.start, true, true));
//logger.warn("Skipped emitting another candle for minute %s, last %s", this.lastCandleMinute, utils.date.toDateTimeStr(latestCandle.start, true, true));
return;
}
this.lastCandleMinute = latestCandle.start.getUTCMinutes();
if (nconf.get("serverConfig:backtest:cacheCandles") && nconf.get('trader') === "Backtester")
this.candleCache = this.candleCache.concat(candles);
super.emitCandles(candles)
//for (let i = 0; i < candles.length; i++)
//logger.verbose("emitting candle: %s", utils.date.toDateTimeStr(candles[i].start, true, true));
super.emitCandles(candles);
}

protected emitCurrentCandle(candle: Candle.Candle) {
Expand Down Expand Up @@ -156,6 +170,10 @@ export class CandleMaker<T extends TradeBase> extends CandleStream<T> {
this.buckets.delete(bucket[0]);
candles.push(candle);
}
// ensure candles are sorted by date ascending
candles = _.sortBy(candles, (candle) => {
return candle.start ? candle.start.getTime() : 0;
});

return candles;
}
Expand Down Expand Up @@ -218,7 +236,7 @@ export class CandleMaker<T extends TradeBase> extends CandleStream<T> {
if (!amount)
return candles;

let start = new Date(previousEndTime ? previousEndTime : _.first<Candle.Candle>(candles).start);
let start = new Date(previousEndTime ? utils.date.dateAdd(previousEndTime, "minute", 1) : _.first<Candle.Candle>(candles).start);
const end = _.last<Candle.Candle>(candles).start;
let i, j = -1;

Expand All @@ -239,6 +257,7 @@ export class CandleMaker<T extends TradeBase> extends CandleStream<T> {
const emptyCandle = new Candle.Candle(this.currencyPair);
emptyCandle.exchange = this.exchange;
emptyCandle.start = new Date(start);
emptyCandle.start.setUTCSeconds(0, 0);
emptyCandle.open = lastPrice;
emptyCandle.high = lastPrice;
emptyCandle.low = lastPrice;
Expand Down

0 comments on commit 1fdcd42

Please sign in to comment.