Gekko Forum
Interact with the UI - Printable Version

+- Gekko Forum (https://forum.gekko.wizb.it)
+-- Forum: Gekko (https://forum.gekko.wizb.it/forum-13.html)
+--- Forum: Technical Discussion (https://forum.gekko.wizb.it/forum-23.html)
+--- Thread: Interact with the UI (/thread-1440.html)



Interact with the UI - tommiehansen - 02-06-2018

Any way to post things to ui; any way to hook into it and perform stuff?

I'm thinking like this (this will not work, but example...):

var strat = {

 end: function()
 {
   alert('Finished in in X time');
 }

}

This could further be expanded and do more useful things such as this:

var strat = {

  say: function( text )
  {
    if ('speechSynthesis' in window)
    {
      let utterance = new SpeechSynthesisUtterance(text);
      utterance.lang = 'en-US';
      speechSynthesis.speak(utterance);
    }
  },

  end: function()
  {
    this.say('Finished in X time');
  }


} // strat{}


Codepen demo:
https://codepen.io/tommiehansen/pen/NyRgBP

Input something into input and press return.
If your browser has support for speechSynthisis it will say what you wrote.


RE: Interact with the UI - askmike - 02-07-2018

[moved this topic to tech discussion]

Interesting idea, right now the strats don't run in a browser so there is no direct communication possible.

I am working on updating the event system (see here), after with at some point even a customStratEvent that your strat can emit. They will all be reachable in the browser (or your own client subscribed to the websocket / zmq / redis pubsub). Would that allow for whatever you are trying to do?

Mean idea being that I want to keep strategies dumb and stateless, if you want your computer to play a song everytime your strat adviced a trade you can simply create a plugin / script that works with every other strategy as well.


RE: Interact with the UI - tommiehansen - 02-07-2018

Maybe, but the UI is already aware of an end() ... ?

This since it posts the performance analysis after finished, it just isn't the end() defined within strategies
since that end() only have the ability to post stuff to the terminal.

The strategies would still be dumb and simple, this would just be strat.ui.end = function(){ alert('hello world'); } or whatever one wanted.
The complexity, just as it is now, would still be up to the user (which is a good thing since it's more flexible and becomes easier to test/write).


RE: Interact with the UI - askmike - 02-07-2018

> Maybe, but the UI is already aware of an end() ... ?

Both the UI and the CLI version are aware of end(), since only backtests actually have any end date. If you run a backtest via the CLI you'll get a similar report at the end.

> The strategies would still be dumb and simple, this would just be strat.ui.end = function(){ alert('hello world'); }

What does it mean for a strategy to end? Strategies don't have any end(), just other parts of the code in case a backtest is ran (that have to do a final report log or cleaning up DB handlers or so). But besides that, I'm really not sure what your example is supposed to do.. What if there is no browser connected? What if there are 10 browsers connected? What if this isn't run via any UI at all?


RE: Interact with the UI - tommiehansen - 02-07-2018

Both the UI and the CLI version are aware of end(), since only backtests actually have any end date. If you run a backtest via the CLI you'll get a similar report at the end.

Yes, the difference is that one cannot post (or add) anything to the UI even though possible (performance analyzer does it).
Do note that end() is just an example and that the example is just an example of something one could do.

What does it mean for a strategy to end? Strategies don't have any end(), just other parts of the code in case a backtest is ran (that have to do a final report log or cleaning up DB handlers or so). But besides that, I'm really not sure what your example is supposed to do.. What if there is no browser connected? What if there are 10 browsers connected? What if this isn't run via any UI at all?


I means what you have written it means, from the docs:

// Optional for executing code
// after completion of a backtest.
// This block will not execute in
// live use as a live gekko is
// never ending.
strat.end = function() {
  // your code!
}

--

Interacting with the UI would be as useful/not useful as posting things to the terminal using log.debug()
or doing any other type of interaction. It's the same reason you opted to post results of the
Performance Analyzer to the UI? So basically as useful/not useful as that.

If there is no UI connected the output of the UI-performance analyzer wouldn't work either which currently is not a problem?
So i don't see the problem since there clearly is some condition that say UI true/false and does different things depending on that
just like you write.

if( this.ui ) alert('hello world'); // browser
else log.debug('hello world'); // terminal


RE: Interact with the UI - askmike - 02-08-2018

> I means what you have written it means, from the docs:
>
> strat.end = function() {
> // your code!
> }

Damn, not sure if these docs are stil up to date. You could easily verify this by logging something there and running a backtest. If they are right you just outsmarted me on what Gekko can do Wink

-------

I think I get the point of what you are trying to do, and I am definitely working on a big upgrade which will enable all of this (just in a different way). Have a look at this PR: https://github.com/askmike/gekko/pull/1850

Specifically have a look at this (work in progress) new documentation file: https://github.com/askmike/gekko/blob/7caf0d31a6d4ea102939d1d8ebbf775ce1c9dac9/docs/internals/events.md

When I am done I will add a custom event your strat can emit, and any other plugin can listen to it (these events will also be sent to the browser, but not as hidden as the performanceAnalyzer currently does it). The next step would be a way to hook into this event in the UI and run whatever code you want. There are a two ways I am thinking about:

- introduce a new type of plugins ("UI plugins")
- extend the current plugin type to have "UI handles" that are actually run in the UI <- this one is probably best in the long run: this way a plugin can "register" JS to be run in the UI, enabling custom widgets and such.

It's important to note that I do NOT want your strat to have code that will be run in the UI automatically, for a number of reasons:

- There might not be an UI, or the UI might not be running when the event happens.
- There might be multiple UIs running looking at the same strat.
- It's a big security risk, strats now have the opportunity to run a browser context (of a potentially different machine).
- Some people are working on a native mobile Gekko App, these might not be able to execute client side javascript (or if they can it's another security risk).


RE: Interact with the UI - tommiehansen - 02-09-2018

This is already what i do with e.g. my own performance measurement that measures how long it takes to run a strategy.

But i also currently use the end() function to output custom strategy statistics e.g. min/max for an indicator.
This in order to simply debug the run or see if there's some values that indicate that the strategy params should be changed in a certain direction.

In that way the end() -function is great and works just as expected.

If you  try the RSI BULL/BEAR that i have shared on these forums and set this.debug = true (custom debug) at init() you'll see that there
are statistics about min/max RSI for two different types of periods (bull/bear) and that you get the total run time
for how long it took to backtest the strategy etc.

All that stuff rely on the end() function since one wouldn't want to output all those messages on each candle.

It also would seem that you initially was talking about the finish() function? If i try to modify that the strategy crashes no
matter what one write. It would seem that finish() is the one responsible for doing cleanup and end-type of processing.

It would therefor seem that you have done this:
end: Something that occurs when a backtest ends and that a user can customize
finish: general cleanup that occurs when everything is completed

So... you already do what i would want, but with the major difference being that one cannot output stuff to the UI
or modify performance analyzer to include custom data (since perfAnalyzer is 'hidden' as you say).

---

What i translate all the other stuff to is:

"
 Hi, here's my strategy.
 Download strategy.js
 put in /gekko/strategies
 npm install bloated_library
 npm install awful_library
 download strategy.helpers.js, put in plugins folder (this makes use of function a, b, y from bloated_library and q, d, e from awful_library)
 run and if you have port 58833 open it migh work, else npm install security_hell and try again
"

..instead of:
"
 Hi, here's my strategy.
 download strategy.js
 put in /gekko/strategies
 run
"

What i'm basically talking about is commonly called dependency hellSmile
(yes, this was harsh... but uneccessary npm installs and over 10x dependencies isn't uncommon)

---

I even think that the TOML-files for strategies is unneeded since these files could just get auto-created on first strategy init (and changed if the strategy settings changes).

I would rather just see all that stuff be defined iniline within the strategy. That way the strategies becomes even simpler.

// pseudo code, doing this.settings.STUFF = 10 already does work though

init: function(){
  // settings "A" for strategy; basically would equals toml [section a]
  this.settings.section_a.HELLO = 10;
  this.settings.section_a.WORLD = 20;

  // settings "B" for strategy... which would equal [section b]
  this.settings.section_b.HELLO = 10;
  this.settings.section_b.WORLD = 20;
}

// somewhere else (pseudo code)
// create toml-file if not exist or modify if exist but strategy params has changed

if( this.strategy.toml || this.strategy.toml.settings !== this.strategy.settings )
  writeTOML( this.strategy.settings );


---

It's important to note that I do NOT want your strat to have code that will be run in the UI automatically, for a number of reasons:

- There might not be an UI, or the UI might not be running when the event happens.
- There might be multiple UIs running looking at the same strat.
- It's a big security risk, strats now have the opportunity to run a browser context (of a potentially different machine).
- Some people are working on a native mobile Gekko App, these might not be able to execute client side javascript (or if they can it's another security risk).

1. Yes, but performance analyzer seems to have already solved this? It outputs to terminal if not running UI and outputs to UI if running ui. There's even a "if(ui.connected)" if i remember correctly. I think you're thinking LIVE while i'm thinking BACKTEST, these two differ quite a lot.

2. This already seems to work though; again -- the performance analyzer outputs stuff and it doesn't matter if i got 10x tabs with 10x gekkos? The perf analyzer will still output unique results on a per-browser level so it already seems to be solved?

3. Yes, but having people download custom plugins that may have a lot of dependecies and stuff is an even greater security concern? More code does not increase security since it increases the attack surface. I do not understand the rationale behind more code/dependecies = increased security.

4. The UI already works great on anything that has a browser?

---

I do understand why you don't want 10x hooks to the UI though.

The simpler solution would just be this:
1. Allow user to customize the performance analyzer object e.g:

end: function(){

 // get (object?)
 let pa = this.performanceAnalyzer;

 // modify
 pa.result.custom.Stuff = 'Some stuff';
 pa.result.custom.Other_stuff = 'Some other stuff';

 // write changes
 this.performanceAnalyzer = pa;

}


2. Implement 'messages' as a 1st class citizen within Gekko (no plugins...):

msg.alert('hello world')
msg.log('hello world')
msg.speak('hello world')

...etc...

// somewhere else....
msg: {

 alert: function( str ){
   if( ui.connected ) alert(str)
   else log.debug(str)
  },

  confirm: function( str ){
    if( confirm(str) ) return true;
    else return false;
  },

  log: function( str ){
    if( ui.connected ) console.log(str); // log to browser console
    else log.debug(str); // log to terminal
  },

  // yeah, this is more for fun; but could be used e.g.
  // msg.speak('Backtest finished in 2 minutes and 4 seconds')
  speak: function( str ){
    if( ui.connected ){
      // check support
      if( 'speechSynthesis' in window ){
         let utterance = new SpeechSynthesisUtterance( str );
         utterance.lang = 'en-US';
         speechSynthesis.speak(utterance);
      }
      else { this.alert( str ); }
    }
    else { log.debug(str); } // no ui -- just log it
  }
  
}

--

I've tried hacking around without modifying the core Gekko files but haven't been successful yet. :-)