Warning: session_start(): open(/var/lib/php/sessions/sess_olbkcmp2l6rl3u1ps2d305qq0q, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
persistable sclass MultiCallbackJuicer {
// Must have at least one level, otherwise no closing at all
sclass Level {
// At juice value minJuiceValue, define the callback rate.
// Callback rates are interpolated between levels.
settable double minJuiceValue;
settable double callback;
toString { ret "Callback " + keepPercentage + "% starting at " + formatDouble2(minJuiceValue); }
}
settableWithVar new L levels;
// Highest juice value seen
settableWithVar double crest = -infinity();
settableWithVar double currentCallback;
{
onCalculatingCloseSignals(signals -> {
if (juiceValue > crest)
crest(juiceValue);
currentCallback(callbackForJuiceValue(crest));
var signal = new CloseSignal().createdBy(this).reason(formatDouble2(currentCallback) + "% Callback");
signal.strength(doubleRatio(crest-juiceValue, currentCallback)*100);
signals.add(signal);
});
}
double callbackForJuiceValue(double juice) {
for (int i = l(levels)-1; i >= 0; i--) {
Level level = levels.get(i);
if (juice < level.minJuiceValue)
continue;
Level nextLevel = get(levels, i+1);
if (nextLevel == null)
ret level;
ret blend(level.keepPercentage, nextLevel.keepPercentage,
transformToZeroToOne(juice, level.minJuiceValue, nextLevel.minJuiceValue));
}
ret empty(levels) ? 1000 : first(levels).callback;
}
void addLevel(double minJuiceValue, double callback) {
levels.add(new Level().minJuiceValue(minJuiceValue).callback(keepPercentage));
}
toString {
ret commaCombine(
shortClassName(this),
levels,
crest == -infinity() ? null : "Highest profit seen: " + formatDouble2(crest),
"Current callback: " + formatDouble2(currentCallback),
);
}
void copyTransientValuesFrom(AbstractJuicer juicer) {
if (juicer cast MultiCallbackJuicer)
crest(juicer.crest);
}
}