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

134
LINES

< > BotCompany Repo | #1036152 // MPM2 backup untested

JavaX fragment (include)

replace real with double.
replace Real with Double.

srecord noeq MPM2(real[] ticker) {
  // how much percentual slippage we have for each position on
  // average dependent on the market (trading site) we are using
  srecord Market(real adversity) {}
  
  srecord Juicer(real lossTolerance, real pullback) {}

  srecord Position(real openingTime, real direction) {}
  
  srecord noeq LiveTicker(real[] data, int time) {
    Real currently() { ret lookback(0); }
    Real lookback(real time) {
      int index = iceil(this.time-1-time);
      ret index >= 0 ? data[index] : null;
    }
    
    void add(real value) {
      if (time >= l(data)) {
        data = resizeArray(data, max(1, limitToSafeArraySize(l(data)*2L)));
        if (time >= l(data)) fail("Can't handle more than 2 billion ticker entries");
      }
      data[time++] = value;
    }
  }

  srecord Eye(real time, real minMove) {
    real adviseDirection(LiveTicker ticker) {
      Real currently = ticker.currently();
      if (currently == null) ret 0;
      Real before = ticker.lookback(time);
      if (before == null) ret 0;
      real move = currently-before;
      if (abs(move) >= minMove) ret (real) sign(move);
      ret 0;
    }
  }

  real ticker(real time) { ret ticker(iceil(time)); }

  real openingPrice(Position p) { ret ticker(p.openingTime); }

  // all "profit" functions return a positive or negative percent value
  real profit(Position p, real time, Market m) {
    ret (ticker(time)/openingPrice(p)*100-100)*p.direction - m.adversity;
  }

  Real closingTime(Position p, Juicer j, Market m) {
    int time = iceil(p.openingTime);
    real openingPrice = ticker(time);
    real crest = -infinity();
    while (time < ticker.length-1) {
      real profit = profit(p, time, m);
      crest = max(crest, profit);
      if (profit < (profit < 0 ? -j.lossTolerance : crest-j.pullback)) break;
      ++time;
    }
    null;
  }

  Real profit(Position p, Juicer j, Market m) {
    Real closingTime = closingTime(p, j, m);
    ret closingTime == null ? null : profit(p, closingTime, m);
  }

  // How profitable is it to open a position of any direction
  // at a certain point in time?
  Real profitability(real time, Juicer j, Market m) {
    ret maxAllowingNull(
      profit(new Position(time, -1), j, m), 
      profit(new Position(time,  1), j, m));
  }
  
  abstract class Convergent extends ItIt<Real> {
    Real value;
    bool stepped, done;
    
    public bool hasNext() {
      if (done) false;
      
      if (!stepped) {
        stepped = true;
        step();
      }
      
      ret !done;
    }
    
    public Real next() {
      assertTrue(hasNext());
      stepped = false;
      ret value;
    }
    
    abstract void step();
  }
  
  // eye can be null, then we just test the juicer
  record noeq Backtest(Eye eye, Juicer j, Market m) extends Convergent {
    Iterator<Int> openingTimes = new WeightlessShuffledIterator<Int>(intRangeList(ticker.length));
    new Average profitPerPosition;
    
    new Average positionsOpenedPercentage;
    
    // percentage of positions closed before reaching the end of the ticker "tape"
    new Average positionsClosedInTimePercentage;
    
    void step {
      if (!openingTimes.hasNext())
        ret with done = true;
        
      int openingTime = openingTimes.next();
      
      Real profit;
      if (eye == null)
        profit = profitability(openingTime, j, m);
      else {
        real direction = eye.adviseDirection(new LiveTicker(ticker, openingTime));
        positionsOpenedPercentage.addSample(direction != 0 ? 100 : 0);
        if (direction == 0)
          ret;
        Position position = new Position(openingTime, direction);
        profit = profit(position, j, m);
      }
      
      positionsClosedInTimePercentage.addSample(profit != null ? 100 : 0);
      if (profit != null)
        profitPerPosition.addSample(profit);
      value = profitPerPosition!;
    }
  }
}

Author comment

Began life as a copy of #1036148

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1036152
Snippet name: MPM2 backup untested
Eternal ID of this version: #1036152/2
Text MD5: d9aa50c1837b83965f4784e733b73844
Author: stefan
Category: javax / trading bot
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-10-01 06:21:14
Source code size: 4081 bytes / 134 lines
Pitched / IR pitched: No / No
Views / Downloads: 7 / 9
Version history: 1 change(s)
Referenced in: [show references]