Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

159
LINES

< > BotCompany Repo | #1036571 // NGSStrategy backup

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (31271L/199K).

// 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 double maMinMove2 = 0.05; // MA trend threshold 2 (hysterisis)
  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
      maDirection maDirectionHistory
      maMoveHistory blockLongHistory blockShortHistory
      longConditionHistory shortConditionHistory
    ]]);
  }
  
  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;
  settable int maDirection;
  
  gettable TickerSequence maMoveHistory = new TickerSequence("maMove");
  gettable TickerSequence blockLongHistory = new TickerSequence("blockLong");
  gettable TickerSequence blockShortHistory = new TickerSequence("blockShort");
  gettable TickerSequence longConditionHistory = new TickerSequence("longCondition");
  gettable TickerSequence shortConditionHistory = new TickerSequence("shortCondition");
  gettable TickerSequence maDirectionHistory = new TickerSequence("maDirection");

  void ngsStep aka ngsLogic() {
    double close = currentPrice();
    double drift = drift();
    
    longCondition(doLongs && close > upperBand() && close < upperMaxDistanceBand() && maRising());
    shortCondition(doShorts & close < lowerBand() && close > lowerMaxDistanceBand() && maFalling());
    
    longConditionHistory?.addIfPriceChanged(boolToInt(longCondition), currentTime());
    shortConditionHistory?.addIfPriceChanged(boolToInt(shortCondition), currentTime());

    if (ma2 > ma1 || close > lowerReturnBand())
      unblockShort();

    if (ma2 < ma1 || close < upperReturnBand())
      unblockLong();

    if (!inCooldown() && drift == 0) {
      if (longCondition && !blockLong) {
        openLong();
        blockLong(true);
      }
  
      if (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<CandleBasedIndicator> 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() { ret maDirection > 0; }
  bool maFalling() { ret maDirection < 0; }
  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());
      if (maMove >= maMinMove)
        maDirection(1);
      else if (maMove <= -maMinMove)
        maDirection(-1);
      else if (maDirection < 0 && maMove >= -maMinMove2
        || maDirection > 0 && maMove <= maMinMove2)
        maDirection(0);
      maDirectionHistory?.addIfPriceChanged(maDirection, 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()
    );
  }
  
  void afterStep :: before {
    blockLongHistory?.addIfPriceChanged(boolToInt(blockLong), currentTime());
    blockShortHistory?.addIfPriceChanged(boolToInt(blockShort), currentTime());

  }
}

Author comment

Began life as a copy of #1036558

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

-
Snippet ID: #1036571
Snippet name: NGSStrategy backup
Eternal ID of this version: #1036571/1
Text MD5: 308e6a1d70e461e4eac6b5d628fd428b
Transpilation MD5: 7529bdffd8940eddc4bca741be49fc87
Author: stefan
Category: javax / trading
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-03-14 12:08:53
Source code size: 5356 bytes / 159 lines
Pitched / IR pitched: No / No
Views / Downloads: 124 / 169
Referenced in: