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

105
LINES

< > BotCompany Repo | #1036520 // CleanMoveStrategy (backup using forward moves)

JavaX fragment (include)

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;
  
  // How often to start a new move analysis (seconds)
  settable double newMoveInterval = 30;
  
  Set<LivePullbackToProfitAnalysis> ongoingMoves = syncLinkedHashSet();
  
  settable long lastMoveStarted;
  
  S fieldsToReset() {
    ret lines(ll(super.fieldsToReset(), [[ongoingMoves lastMoveStarted]]));
  }
  
  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();
    }
    
    if (startTime == 0) startTime = currentTime();
    
    // 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);
      }
    }
    
    // Start new move calculator
    var time = currentTime();
    if (time >= lastMoveStarted+fromSeconds(newMoveInterval)) {
      lastMoveStarted = time;
      for (isShort : ll(false, true))
        ongoingMoves.add(new LivePullbackToProfitAnalysis().isShort(isShort));
    }
    
    // Update moves
    for (move : cloneList(ongoingMoves)) {
      move.feed(new PricePoint(time, price));
      if (move.done())
        ongoingMoves.remove(move);
    }
    
    // Check if we should start a position
    if (empty(openPositions())) {
      bool shouldShort = false, shouldLong = false;
      PullbackToProfit openReason = null;
      
      for (move : ongoingMoves)
        if (move.cleanness() >= minCleanness && move.profit() >= minProfit) {
          openReason = move.ptp();
          if (openReason.isShort)
            shouldShort = true;
          else
            shouldLong = 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);
      }
    }
  }
  
  L<? extends Position> openPositions() { ret (L) super.openPositions(); }
  
  LS status() {
    ret listCombine(
      "Ongoing moves: " + n2(ongoingMoves),
      super.status()
    );
  }
}

Author comment

Began life as a copy of #1036518

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): elmgxqgtpvxh, mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1036520
Snippet name: CleanMoveStrategy (backup using forward moves)
Eternal ID of this version: #1036520/4
Text MD5: b822e49297abec6a625db95813539457
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 13:40:35
Source code size: 3157 bytes / 105 lines
Pitched / IR pitched: No / No
Views / Downloads: 67 / 75
Version history: 3 change(s)
Referenced in: [show references]