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

118
LINES

< > BotCompany Repo | #1036518 // CleanMoveStrategy [OK, for one coin at a time]

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

Libraryless. Click here for Pure Java version (30155L/190K).

concept CleanMoveStrategy extends G22TradingStrategy {
  // How clean the move must be
  settable double minCleanness = 2;
  
  // How profitable the move must be
  settable double minProfit = 0.5;
  
  // Factor for turning pullback into callback
  settable double callbackFactor = 1.5;
  
  // Max pullback of move
  settable double maxPullback = 1;
  
  // Price has to move at least this many percent for us to
  // recalculate the moves
  //settable double minChangeToReactTo = 0.1;
  
  // How often to start a new move analysis (seconds)
  settable double calcMovesEvery = 30;
  
  S fieldsToReset() {
    ret lines(ll(super.fieldsToReset(), [[currentMoves lastPriceReactedTo movesCalced]]));
  }
  
  // current short & long move
  settable L<LivePullbackToProfitAnalysis> currentMoves;
  
  //settable double lastPriceReactedTo;
  settable double movesCalced;
  
  persistable class Position extends G22TradingStrategy.Position {
    settable CallbackJuicer juicer;
  }
  
  srecord ProfitBeforeLeverageJuiceable(Position p) is Juiceable {
    public double juiceValue() { ret p.profitBeforeLeverage(); }
  }
  
  void price(double price) {
    if (currentPrice == price) ret;
    currentPrice = price;
    afterwards { afterStep(); change(); }
    
    // Close positions
    
    for (p : openPositions()) {
      if (p.juicer != null) {
        var signals = p.juicer.calculateCloseSignals();
        var strongest = highestBy(signals, s -> s.strength());
        if (strongest != null && strongest.isTrigger())
          p.close(strongest);
      }
    }
    
    // Check if we should start a position
    if (empty(openPositions()) && shouldCalcMoves()) {
      // Calculate 2 current moves backwards in time
      var time = currentTime();
      currentMoves = map(falseTrue(), isShort -> {
        new LivePullbackToProfitAnalysis a;
        a.pullbackLimit(maxPullback);
        a.isShort(isShort);
        int idx = actualTicker.indexOfTimestamp(currentTime());
        while (idx >= 0 && !a.done())
          a.feed(actualTicker.getPricePoint(idx--));
        ret a;
      });
    
      bool shouldShort = false, shouldLong = false;
      PullbackToProfit openReason = null;
      
      for (move : currentMoves)
        for (ptp : move.ptpList())
          if (ptp.cleanness() >= minCleanness && ptp.profit() >= minProfit) {
            openReason = ptp;
            if (openReason.isShort)
              shouldLong = true;
            else
              shouldShort = true;
          }
        
      if (shouldShort && shouldLong)
        print("Conflicting signal (long+short at once)");
      else if (shouldShort || shouldLong) {
        int direction = shouldShort ? -1 : 1;
        new Position p;
        p.marginToUse = marginPerPosition;
        var callbackRate = openReason.pullback*callbackFactor;
        p.juicer = new CallbackJuicer(callbackRate);
        p.juicer.juiceable(new ProfitBeforeLeverageJuiceable(p));
        openPosition(p, direction, openReason);
      }
    }
  }
  
  bool shouldCalcMoves() {
    /*if (!differentByEpsilonRatio(lastPriceReactedTo, currentPrice, minChangeToReactTo/100))
      false;
    lastPriceReactedTo(currentPrice);
    true;*/
    
    var time = currentTime();
    if (time >= movesCalced+fromSeconds(calcMovesEvery)) {
      movesCalced = time;
      true;
    }    
    false;
  }
  
  L<? extends Position> openPositions() { ret (L) super.openPositions(); }
  
  LS status() {
    ret listCombine(
      map(currentMoves, move -> "Move: " + move),
      super.status()
    );
  }
}

Author comment

Began life as a copy of #1036259

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1036518
Snippet name: CleanMoveStrategy [OK, for one coin at a time]
Eternal ID of this version: #1036518/24
Text MD5: 94555821f69917dc9700d40612fc0f9f
Transpilation MD5: adc080c1457fd60eee2d546e040f7598
Author: stefan
Category: javax / trading
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-01-22 17:06:35
Source code size: 3681 bytes / 118 lines
Pitched / IR pitched: No / No
Views / Downloads: 115 / 257
Version history: 23 change(s)
Referenced in: [show references]