[BOUNTY] Transform a Pine Script indicator to a Gekko indicator
#1
08.02 Edit:

Since my OP wasn't informative enough I am adding here what I would like from this indicator:

1) I would like the indicator to return different attributes about the current given candle size (15m, 1H, 2H etc) in such a way that they could be used in strategies. The indicator returns a lot of information in any given timeframe and I would like to be able to use that information as much as possible. Also it needs just 4 candles to warm up;

2) I would like to be able to run and also backtest this indicator on a live market in the any timeframe that I want. Let's say 1H. I would like the indicator to continuously (live) check the status of the current candle and to return what number it represents in a setup or countdown counter (1 green/red, 2 green/red, 3 green/red etc). After reporting the number of the candle I would like the strategy to act upon this returned number and give long or short signal based on somehow custom attributes. For example I am interested in a strategy that sounds like this: When candle 2 starts trading above/below candle 1 then long/short. This would be to open the trade. I'll get to the closing the order in a second.

3) About closing the order or giving the short/long signal. MeanSquaredError told me in a private message:

"Right now the strategy just issues a 'short' or 'long' advice to Gekko once the TD countdown is completed. If by SL and TP you mean the stop-loss and take-profit, then I guess I can implement something like that, but the real problem is that the custom strategy does not see separate orders. The strategy just gives Gekko's portfolio manager to go 'short' or 'long'. So if we have issued a 'long' advice, then after a while we can sort of close that order by giving a 'short' advice. But we can not even be sure what amount has Gekko sold after our advice.

I guess we can discuss this with Mike and see whether he is willing to make changes to Gekko that would make possible the development of more complex strategies."

@Mike are you planning on stop-loss and take-profit capabilities on trades? Also how does the bot operates in live trading? It just does a market buy/sell with all the account balance?

I guess this could be coded as a series of ifs>else until this is implemented.

Added more:

3) In TradingView when looking at a timeframe with the TD Indicator sometimes the candles have 2 numbers on them. The first (principal) number above the candle and the second (secondary) number below and for example there can be candle with a 3 green on top and 10 red below. Would that be possible in Gekko?;

4) Would it be possible to differentiate between perfected 9s and imperfected 9s?;

5) Would it be possible to tell where the TDST line is at any given time if there is any?

P.S. If you think that the bounty is too low for what I'm asking speak up!

*********************************************************************************************************************************************


Hello,
Looks like I will be creating the first bounty. I am open to counter offers and to discussion in general.

I would like to be able to use the TD Indicator (Tom DeMark Indicator) with Gekko. I have the indicator written in Pine Script (TradingView script).

I'm offering 0.01 BTC as bounty and I will send 0.011 as escrow in order to cover for the miner fees.

Not sure what else can I offer as information. Ask away!
  Reply
#2
Great stuff! Let's hope someone picks this up.

As for the bounty:

- Could you provide a link to the indicator on Tradeview.
- There are some differences with how Gekko and Tradeview aggregate data, which means that even if the implementation is 100% correct there might still be minor differences in output. Is this acceptable?
- Tradeview does more than give out signals: it can also draw lines and points on the chart, this is not (yet) supported for Gekko. Would it be acceptable that the strategy only gives out signals (either buy or sell)?

If you agree with all the above you can send the bitcoin to me (I am the escrow), this is the address you can send it to: bc1qg76t7nzv6c88fxkhp97fvmaj5s0lk202hdel7s
  Reply
#3
1) There is no link as the indicator is private. I can provide this under some form of consensual NDA at least in it's original form;
2) This is new. It depends on the differences in the output. Can you provide a bit more info in this?;
3) Totally yes. This indicator and strategy doesn't need any kind of drawing. That is, for me, a totally separate thing.

Since this is the first time you/we are doing this, I think that we should consider how should bounties be approached. Do you/we want the bounty address public? Personally I would like to be kept private, but of course this puts more burden on you and maybe requiring a bit more resources from you.

Big thumbs up for the native SegWit address!
  Reply
#4
Very understandably that the original indicator is private. Two more questions though:

- Does it matter if the Gekko indicator becomes public?
- How are we (the community) or I (the escrow) supposed to check whether someone implemented the indicator correctly? Not sure how to do this without seeing the original indicator. I am trying to go to a situation where people who claim bounties always get paid, regardless of the original poster still being around.

> Do you/we want the bounty address public?

This can be fully private, as long as it's clear to everyone when the funds are in escrow (see my point above).

EDIT:

> 2) This is new. It depends on the differences in the output. Can you provide a bit more info in this?

Gekko calculates candles based on whatever time Gekko is started: if you want hourly candles TradeView will force the candles to start at :00 every hour (one candle for 10:00 until 11:00), whereas with Gekko this is not the case. On top of that some indicators are calculated differently (depending on what kind of indicators your strategy require this might or might not be a problem).
  Reply
#5
"- Does it matter if the Gekko indicator becomes public?"

Well, it doesn't matter. I agree with it becoming public. I would just like a social agreement to not spread the original version on the internet. If someone wants to try to transform it from Gekko to Pine he is free to do it, but he should work for it Smile

"- How are we (the community) or I (the escrow) supposed to check whether someone implemented the indicator correctly? Not sure how to do this without seeing the original indicator. I am trying to go to a situation where people who claim bounties always get paid, regardless of the original poster still being around."

Good question. I would gladly provide the source code to you or to any capable reviewer. I just don't want the original source to be available for everyone. The main indicator rules can be found on the internet so at least its general form can be easily checked by almost anyone that can use a computer.

"> Do you/we want the bounty address public?"

This is a hard question. Normally if the address is public everyone can check how big is the bounty, but puts the original poster's privacy at risk. If the address is kept private you would have to monitor and update every bounty every time the bounty increases. This seems a bit hard for you in the long run. Since this is the first bounty I would like to keep it private and also I would like to help you for the effort!

"This can be fully private, as long as it's clear to everyone when the funds are in escrow (see my point above)."

People will have to trust you. I don't see any other way around. Since it's just the start of this bounty program and the amounts are small I don't see it as an real issue right now.

"Gekko calculates candles based on whatever time Gekko is started: if you want hourly candles TradeView will force the candles to start at :00 every hour (one candle for 10:00 until 11:00), whereas with Gekko this is not the case. On top of that some indicators are calculated differently (depending on what kind of indicators your strategy require this might or might not be a problem). "

The first issue is easy to solve. Just start Gekko at :00 and you are ok. For the second issue we will find out when the time comes. I don't worry about that.
  Reply
#6
Sounds great! You are very right about situations where more people want to add money to the bounty.

I do see the privacy implications of having public bounty addresses, however it would also be good (mostly from my perspective) to have some kind of a public audit trail so people see what is being talked about on the forum. Besides that the person claiming the bounty will be able to track your address by looking at the transaction history.

Bounty rules

- Once I received the bounty bitcoin I will post here that the bounty is active (Road.Apps I will PM you a new address which I shall not disclose publicly).
- Everyone who wants to enter this bounty can PM Road.Apps for the pine script. he/she shall agree to NOT share the this original Pinescript.
- I do not need access to the original pinescript for now. Once a PR is ready I'll ask Road.Apps if it seems correct, if there is uncertainty about this I will come in and verify this.
  Reply
#7
Bounty sent.
  Reply
#8
Bounty received, this bounty is now active to be completed & claimed!
  Reply
#9
Hi,
I added the initial version of the Tom Demark's Sequential indicator and created a simple strategy that uses the new indicator. You can get them here:

https://github.com/MeanSquaredError/gekk...f46ee4bbaf

The internal organization of the TradeView scripts is quite different from the Gekko's internal structure. TradeView displays charts that span a relatively large interval, while Gekko's indicators and strategies are focused on the current moment.

So it is not a direct port, but rather a new implementation of the Tom DeMark's indicator while using the original TradeView script as a reference. Functionally the TradeView script and Gekko's indicator should be equivalent.

One noticeable difference from the indicator as invented by Tom Demark and the TradeView's script (and Gekko's indicator) is that the original indicator requires an initial bearish/bullish flip at the start of the sequence while the TradeView (and Gekko's) strategy don't require the initial flip.


When running the trader, paper trader or backtesting the strategy name is TDM_SEQ.

The candle size can be any size that you want. I was testing it with 1 minute and then with 1 day, but any candle size should do (I guess it mostly makes sense to use 1 day as candle size).

The Warmup period doesn't really matter - the strategy only starts giving advices when there is enough data, so you can safely set the warmup period to 1.

You can watch the debug output in the console. All the messages from the TDM_SEQ strategy are prefixed with "TDM_SEQ(s)".

There are debug messages from the indicator prefixed with TDM_SEQ(i)", but these are commented out. If you can uncomment them in the indicator file, if you want more information about the internal functionality.

Basically the strategy just watches for TDM BUY and issues a "long" advice, or TDM_SELL and then issues a "short" advice. I gave it some limited backtesting and it seems to be detecting the patterns correctly but it really needs more testing.

So everyone is welcome to test it.
  Reply
#10
Hi,
After some testing and discussion with Road.Apps it seems that the current indicator and strategy need more flexibility in order to be usable in live trading. I won't have the time to work on further improvements, because I am busy with other projects, so I will post the current code here in this thread. Anyone willing to take over the implementation of this feature can use the code as a starting point or just as a reference. Mike, please keep the bounty for whomever decides to take over the project (the strategy is not giving very good results in its current form).

The following code goes to
gekko/strategies/TDM_SEQ.js


Code:
var strat = {
 init: function() {
   this.name = 'TDM_SEQ';
   this.numCountdowns = 0;
   this.pendingAdvice = null;
   this.addIndicator('tdmSeq', 'TDM_SEQ');
 },

 update: function(candle) {
   var seqResult;

   this.indicators.tdmSeq.update(candle);
   seqResult = this.indicators.tdmSeq.result;
   if (this.numCountdowns != seqResult.numCountdowns) {
    console.log('TDM_SEQ(s): New complete countdown (', seqResult.lastCdType, ') after candle on', candle.start);
    this.numCountdowns = seqResult.numCountdowns;
    this.pendingAdvice = seqResult.lastCdType;
   }
 },

 log: function () {},

 check: function() {
   switch (this.pendingAdvice) {
   case 'buy':
     console.log('TDM_SEQ(s): Advising long');
     this.advice('long');
     this.pendingAdvice = null;
     break;
   case 'sell':
     console.log('TDM_SEQ(s): Advising short');
     this.advice('short');
     this.pendingAdvice = null;
     break;
   default:
//      console.log('TDM_SEQ(s): Advising none');
     this.advice();
     break;
   }
 }
};

module.exports = strat;

And the following code goes to
gekko/strategies/indicators/TDM_SEQ.js


Code:
/*
* Tom DeMark's Sequential indicator
*
* The return variable is an object with following properties:
*
* numCountdowns: Number of countdowns found so far (integer)
* lastCdType: Last countdown type. Can be 'buy' or 'sell' (string)
* lastCdPerfectSetup: A boolean flag indicating whether last countdown had a perfect setup. (boolean)
*
*/

var Indicator = function() {
 this.histData = [];
 this.histMax = 20;
 this.state = 'none';
 this.perfectSetup = null;
 this.countdownCandles = null;
 this.countdownCandleEight = null;
 this.stateToNone();
 this.result = {numCountdowns: 0, lastCdType: null, lastCdPerfectSetup: null};
//  console.log('TDM_SEQ(i): Created an indicator');
};

Indicator.prototype.update = function(candle) {
 this.addToHistory(candle);
 this.updateFromHistory();
};

Indicator.prototype.addToHistory = function(candle) {
 this.histData.unshift(candle);
 if (this.histData.length > this.histMax) {
   this.histData.pop();
 }
//  console.log('TDM_SEQ(i): Added a candle:', JSON.stringify(candle));
};

Indicator.prototype.updateFromHistory = function() {
/*
 console.log(
   'TDM_SEQ(i): Variables before candle',
   JSON.stringify({state: this.state, perfectSetup: this.perfectSetup, countdownCandles: this.countdownCandles})
 );
*/
 for (;;) {
   if (this.updateAttempt()) {
     break;
   }
   this.stateToNone();
 }
/*
 console.log(
   'TDM_SEQ(i): Variables after candle',
   JSON.stringify({state: this.state, perfectSetup: this.perfectSetup, countdownCandles: this.countdownCandles})
 );
*/
};

Indicator.prototype.updateAttempt = function() {
 switch (this.state) {
 case 'none':
   if (this.checkBuySetup()) {
//      console.log('TDM_SEQ(i): Found a buy setup');
     this.state = 'buy_countdown';
     this.countdownCandles = 0;
     this.perfectSetup = Math.min(this.histData [0].low, this.histData [1].low) < Math.min(this.histData [2].low, this.histData [3].low);
   } else if (this.checkSellSetup()) {
//      console.log('TDM_SEQ(i): Found a sell setup');
     this.state = 'sell_countdown';
     this.countdownCandles = 0;
     this.perfectSetup = Math.max(this.histData [0].high, this.histData [1].high) > Math.min(this.histData [2].high, this.histData [3].high);
   }
   return (true);
 case 'buy_countdown':
   if (this.checkSellSetup()) {
//      console.log('TDM_SEQ(i): Canceling buy countdown because of a sell setup');
     this.stateToNone();
     return (false);
   }
   if (this.histData [0].close <= this.histData [2].low) {
     ++this.countdownCandles;
   }
   if (this.countdownCandles == 8) {
     this.countdownCandleEight = this.histData [0];
   }
   if ((this.countdownCandles >= 13) && (this.histData [0].low <= this.countdownCandleEight.close)) {
     this.addCountdownToResult('buy');
     this.stateToNone();
   }
   return (true);
 case 'sell_countdown':
   if (this.checkBuySetup()) {
//      console.log('TDM_SEQ(i): Canceling sell countdown because of a buy setup');
     this.stateToNone();
     return (false);
   }
   if (this.histData [0].close >= this.histData [2].high) {
     ++this.countdownCandles;
   }
   if (this.countdownCandles == 8) {
     this.countdownCandleEight = this.histData [0];
   }
   if ((this.countdownCandles >= 13) && (this.histData [0].high >= this.countdownCandleEight.close)) {
     this.addCountdownToResult('sell');
     this.stateToNone();
   }
   return (true);
 default:
//    console.log('TDM_SEQ(i): Unknown state', this.state);
   this.stateToNone();
   return (false);
 }
};

Indicator.prototype.checkBuySetup = function() {
 var i;

 if (this.histData.length < 13) {
   return (false);
 }
 for (i = 0; i < 9; ++i) {
   if (this.histData [i].close >= this.histData [i+4].close) {
       return (false);
   }
 }
 return (true);
};

Indicator.prototype.checkSellSetup = function() {
 var i;

 if (this.histData.length < 13) {
   return (false);
 }
 for (i = 0; i < 9; ++i) {
   if (this.histData [i].close <= this.histData [i+4].close) {
       return (false);
   }
 }
 return (true);
};

Indicator.prototype.stateToNone = function() {
 this.state = 'none';
 this.perfectSetup = null;
 this.countdownCandles = null;
 this.countdownCandleEight = null;
};

Indicator.prototype.addCountdownToResult = function(type) {
 ++this.result.numCountdowns;
 this.result.lastCdType = type;
 this.result.lastCdPerfectSetup = this.perfectSetup;
};

module.exports = Indicator;
  Reply


Forum Jump:


Users browsing this thread: