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

173
LINES

< > BotCompany Repo | #1036204 // Corridor2 - the "analog" version that doesn't digitize prices [dev., have to figure out first]

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

Libraryless. Click here for Pure Java version (9969L/55K).

sclass Corridor2 {
  settable double smallMove = 0.2;
  settable int capacity = 6;
  settable bool openTwoPositionsAtStart = true;
  
  record noeq Position(double openingPrice, double direction) {
    double closingPrice = Double.NaN;
    
    bool closed() { ret !isNaN(closingPrice); }
    S type() { ret trading_directionToPositionType(direction); }
    
    double profitAtPrice(double price) {
      ret (price-openingPrice)*direction;
    }
    
    double profit() {
      ret profitAtPrice(closed() ? closingPrice : currentPrice());
    }
    
    void close {
      if (closed()) fail("Can't close again");
      openPositionsMap(direction).remove(openingPrice);
      closingPrice = currentPrice();
      closedPositions.add(this);
      realizedProfit += profit();
      print(this);
      printPositions();
    }
    
    toString {
      ret renderFunctionCall(
        spaceCombine(
          closed() ? "Closed" : null,
          type()
        ),
        openingPrice,
        "profit=" + profit());
    }
  }
      
  gettable double currentPrice = 0;
  
  gettable double lastPrice = Double.NaN;
  gettable double startingPrice = Double.NaN;
  gettable double realizedProfit;
  gettable double maxDebtEncountered;
  gettable int stepCount;
  
  // open positions sorted by direction and price
  gettable new TreeMap<Double, Position> openLongs;
  gettable new TreeMap<Double, Position> openShorts;
  
  gettable new L<Position> closedPositions;
  gettable new DoubleBuffer priceHistory;
  
  TreeMap<Double, Position> openPositionsMap(double direction) {
    if (direction > 0) ret openLongs;
    if (direction < 0) ret openShorts;
    fail("direction 0");
  }
  
  Position openPosition(double direction) {
    var p = new Position(currentPrice(), direction);
    openPositionsMap(direction).put(p.openingPrice, p);
    print("Opening " + p);
    printPositions();
    ret p;
  }
  
  Position openShort() { ret openPosition(-1); }
  Position openLong() { ret openPosition(1); }
  
  L<Position> openPositions() {
    ret concatLists(values(openLongs), values(openShorts));
  }
  
  void printPositions {
    var positions = openPositions();
    print(colonCombine(n2(positions, "open position"),
      joinWithComma(positions)));
  }
  
  double unrealizedProfit() {
    ret doubleSum(map(openPositions(), ->.profit()));
  }
  
  L<Position> negativePositions() {
    ret filter(openPositions(), p -> p.profit() < 0);
  }
  
  double debt() {
    ret doubleSum(map(negativePositions(), ->.profit()));
  }
  
  double profit() {
    ret realizedProfit+unrealizedProfit();
  }
  
  LS status() {
    ret ll(
      "Step " + n2(stepCount),
      "Profit: " + profit(),
      "Realized profit: " + realizedProfit + " from " + n2(closedPositions, "closed position"),
      "Unrealized profit: " + unrealizedProfit() + " in " + n2(openPositions(), "open position"),
      "Debt: " + debt(),
    );
  }
  
  toString { ret commaCombine(status()); } 
  
  void prices(double... prices) {
    fOr (price : prices)
      price(price);
  }
  
  void currentPrice aka price(double price) {
    lastPrice = currentPrice;
    
    if (lastPrice == price) ret;
    
    currentPrice = price;

    priceHistory.add(price);
    ++stepCount;
    printWithPrecedingNL(commaCombine(
      "Step " + stepCount + ". Old price: " + lastPrice,
      "New price: " + price));

    step();
    maxDebtEncountered = max(maxDebtEncountered, debt());
    print(this);
  }
  
  bool started() { ret !isNaN(startingPrice); }
  
  void start {
    if (started()) fail("Already started");
    startingPrice = currentPrice();
    print("Starting CORRIDOR at " + startingPrice + " +/- " + smallMove);
    if (openTwoPositionsAtStart) {
      openPosition(1);
      openPosition(-1);
    }
  }
  
  int currentDirection() {
    ret sign(currentPrice-lastPrice);
  }
  
  L<Position> positionsAtPriceOrWorse(double direction, double price) {
    var map = openPositionsMap(direction);
    ret direction < 0
      ? valuesList(map.tailMap(price, true))
      : valuesList(map.headMap(price, true));
  }
  
  // Algorithm-specific logic follows
  
  swappable void step {
    // Close winning position(s)
    
    var positions = positionsAtPriceOrWorse(currentDirection(),
      currentPrice()-currentDirection()*smallMove);
    for (p : positions) p.close();
    
    // If we closed anything, open a position in reverse direction
    if (nempty(positions)) {
      openPosition(-currentDirection());
    }
      
    // TODO: "travelling"
  }
}

Author comment

Began life as a copy of #1036196

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): elmgxqgtpvxh, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1036204
Snippet name: Corridor2 - the "analog" version that doesn't digitize prices [dev., have to figure out first]
Eternal ID of this version: #1036204/11
Text MD5: e1402bffeed571f1edb572b3837d6914
Transpilation MD5: 09659741521ca370c190286f3300a77b
Author: stefan
Category: javax / gazelle 22
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-10-17 23:26:03
Source code size: 4701 bytes / 173 lines
Pitched / IR pitched: No / No
Views / Downloads: 128 / 235
Version history: 10 change(s)
Referenced in: [show references]