persistable sclass CallbackJuicer extends AbstractJuicer {
  settableWithVar double callbackRate = 0.5;

  // Highest juice value seen - we start at 0
  settableWithVar double crest = 0;
  
  *(double *callbackRate) {}
  
  {
    onCalculatingCloseSignals(signals -> {
      if (juiceValue > crest)
        crest(juiceValue);
        
      var signal = new CloseSignal().createdBy(this).reason(formatDouble1(callbackRate) + "% Callback");
      signal.strength(doubleRatio(crest-juiceValue, callbackRate)*100);
      signals.add(signal);
    });
  }
  
  toString {
    ret commaCombine(
      shortClassName(this),
      "Callback rate: " + formatDouble2(callbackRate()),
      "Highest profit seen: " + formatDouble2(crest),
    );
  }
  
  void copyTransientValuesFrom(AbstractJuicer juicer) {
    if (juicer cast CallbackJuicer)
      crest(juicer.crest);
  }
}