Warning: session_start(): open(/var/lib/php/sessions/sess_u073s6ij8eekn2m071sllit7vn, 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
// Design notes.
//
// NG stands for "Non-Garbage"
//
// !Design notes end
sclass NGSStrategy extends G22CandleBasedStrategyWithTrailingStop {
settable double minDistance = 0.4;
settable double maxDistance = 50;
settable int period1 = 100; // the "slow" MA
settable int period2 = 5; // the fast MA (for opening)
settable double maMinMove = 0.07; // MA trend threshold
settable bool doLongs = true;
settable bool doShorts = true;
settable double unblockDistance = 0.8;
// per-run fields
S fieldsToReset() {
ret lineCombine(super.fieldsToReset(), [[
ma1 ma2 lastMA1 longCondition shortCondition blockShort blockLong maMove movingAverage1_cache movingAverage2_cache
maMoveHistory
]]);
}
settable double ma1;
settable double ma2;
settable double lastMA1 = Double.NaN;
settable bool longCondition;
settable bool shortCondition;
settable bool blockLong;
settable bool blockShort;
settable double maMove;
gettable TickerSequence maMoveHistory = new TickerSequence("maMove");
void ngsStep aka ngsLogic() {
double close = currentPrice();
double drift = drift();
longCondition(doLongs && close > upperBand() && close < upperMaxDistanceBand() && maRising());
shortCondition(doShorts & close < lowerBand() && close > lowerMaxDistanceBand() && maFalling());
if (ma2 > ma1 || close > lowerReturnBand())
unblockShort();
if (ma2 < ma1 || close < upperReturnBand())
unblockLong();
if (drift <= 0 && longCondition && !blockLong) {
openLong();
blockLong(true);
}
if (drift >= 0 && shortCondition && !blockShort) {
openShort();
blockShort(true);
}
if (drift > 0 && close < lowerBand())
closeAllPositions("Below band");
if (drift < 0 && close > upperBand())
closeAllPositions("Above band");
}
simplyCached MAIndicator movingAverage1() {
ret new MAIndicator(period1);
}
simplyCached MAIndicator movingAverage2() {
ret new MAIndicator(period2);
}
L indicators() {
ret ll(movingAverage1(), movingAverage2());
}
void unblockLong {
if (blockLong) {
log("Long unblock");
blockLong(false);
}
}
void unblockShort {
if (blockShort) {
log("Short unblock");
blockShort(false);
}
}
bool maRising(dbl maMove default maMove) { ret maMove >= maMinMove; }
bool maFalling(dbl maMove default maMove) { ret maMove <= -maMinMove; }
double moveSignal() { ret maMove/maMinMove*100; }
double upperBand(dbl ma1 default ma1) { ret ma1*(1+minDistance/100); }
double lowerBand(dbl ma1 default ma1) { ret ma1*(1-minDistance/100); }
double upperMaxDistanceBand() { ret ma1*(1+maxDistance/100); }
double lowerMaxDistanceBand() { ret ma1*(1-maxDistance/100); }
double upperReturnBand() { ret ma1*(1+unblockDistance/100); }
double lowerReturnBand() { ret ma1*(1-unblockDistance/100); }
{
granularity(30);
onNewPrice(price -> ngsStep());
onCandleCompleted(candle -> {
lastMA1(ma1);
ma1(movingAverage1()!);
ma2(movingAverage2()!);
maMove((ma1/lastMA1-1)*100);
maMoveHistory.addIfPriceChanged(maMove, currentTime());
ngsStep();
});
}
LS status() {
ret listCombine(
"Min distance, MA min move: " + minDistance + " " + maMinMove + " (current move: " + formatDouble(maMove, 4) + ")",
"MA periods: " + period1 + " " + period2,
"Do: " + commaCombine(stringIf(doLongs, "Longs"), stringIf(doShorts, "Shorts")),
"Moving averages: " + formatDouble_significant(ma1, 4) + ", " + formatDouble_significant(ma2, 4),
valueOrNull(blockLong, "Long blocked"),
valueOrNull(longCondition, "Long condition"),
valueOrNull(blockShort, "Short blocked"),
valueOrNull(shortCondition, "Short condition"),
super.status()
);
}
}