Warning: session_start(): open(/var/lib/php/sessions/sess_r2ik9intko0ddkorhum4n11sg2, 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 MultiPullbackJuicer extends StopLossJuicer {
sclass Level {
// Starting at juice value minJuiceValue, keep keepPercentage of the juice.
// Keep percentages between levels are interpolated linearly.
settable double minJuiceValue;
settable double keepPercentage;
toString { ret "Keep " + keepPercentage + "% starting at " + formatDouble3(minJuiceValue); }
}
settableWithVar new L levels;
// Highest juice value seen
settableWithVar double crest = -infinity();
settableWithVar double currentMaxPullback;
{
onCalculatingCloseSignals(signals -> {
if (juiceValue > crest)
crest(juiceValue);
if (crest < 0) ret;
double keepPercentage = getKeepPercentageForJuiceValue(crest);
if (keepPercentage > 100) ret;
double toKeep = crest*(keepPercentage/100);
currentMaxPullback(crest-toKeep);
var signal = new CloseSignal().createdBy(this).reason("Profit");
if (currentMaxPullback == 0)
signal.strength(1);
else
signal.strength(doubleRatio(crest-juiceValue, currentMaxPullback)*100);
signals.add(signal);
});
}
double getKeepPercentageForJuiceValue(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.keepPercentage;
ret blend(level.keepPercentage, nextLevel.keepPercentage,
transformToZeroToOne(juice, level.minJuiceValue, nextLevel.minJuiceValue));
}
ret 101;
}
void addLevel(double minJuiceValue, double keepPercentage) {
levels.add(new Level().minJuiceValue(minJuiceValue).keepPercentage(keepPercentage));
}
toString {
ret commaCombine(
shortClassName(this),
!stopLossEnabled ? null : "Stop loss: " + formatDouble2(stopLossLimit()),
levels
);
}
}