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

149
LINES

< > BotCompany Repo | #1036148 // MPM2 - Trading Bot v2

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

Transpiled version (11080L) is out of date.

1  
set flag Reparse.
2  
replace real with double.
3  
replace Real with Double.
4  
replace price with float.
5  
6  
srecord noeq MPM2(price[] ticker, long[] timestamps) {
7  
  // How much percentual slippage we have for each position on
8  
  // average plus the fees for the position.
9  
  // Obviously dependent on the market (trading site) we are using.
10  
  srecord Market(real adversity) {}
11  
  
12  
  srecord Position(real openingTime, real direction) {}
13  
  
14  
  record ClosedPosition(Position p, real closingTime) {
15  
    settable Ticker ticker;
16  
    settable real profit;
17  
    
18  
    MPM2 mpm() { ret MPM2.this; }
19  
    
20  
    real openingPrice() { ret MPM2.this.ticker(p.openingTime); }
21  
    real closingPrice() { ret MPM2.this.ticker(closingTime); }
22  
  }
23  
  
24  
  srecord Juicer(real lossTolerance, real pullback) {}
25  
26  
  abstract sclass Eye {
27  
    abstract real adviseDirection(Ticker ticker);
28  
  }
29  
  
30  
  // only the first length items in data and timestamps are looked at
31  
  srecord noeq Ticker(price[] data, long[] timestamps, int length, long currentTime) {
32  
    real currentPrice() { ret data[length-1]; }
33  
    
34  
    Real lookback(real time) {
35  
      int index = binarySearch_insertionPoint(wrapLongArrayAsList(timestamps), lceil(currentTime-time));
36  
      ret index >= 0 ? (real) data[index] : null;
37  
    }
38  
  }
39  
  
40  
  sclass LiveTicker extends Ticker {
41  
    void add(price value, long timestamp) {
42  
      data = addToArrayWithDoublingStrategy(data, length, value);
43  
      timestamps = addToArrayWithDoublingStrategy(timestamps, length, timestamp); 
44  
      length++;
45  
    }
46  
  }
47  
  
48  
  Ticker ticker() { ret new Ticker(ticker, timestamps, l(timestamps), last(timestamps)); }
49  
50  
  srecord SimpleEye(real time, real minMove) extends Eye {
51  
    real adviseDirection(Ticker ticker) {
52  
      Real currentPrice = ticker.currentPrice();
53  
      if (currentPrice == null) ret 0;
54  
      Real before = ticker.lookback(time);
55  
      if (before == null) ret 0;
56  
      real move = currentPrice/before*100-100;
57  
      if (abs(move) >= minMove) ret (real) sign(move);
58  
      ret 0;
59  
    }
60  
  }
61  
62  
  real ticker(real time) { ret ticker[iceil(time)]; }
63  
64  
  real openingPrice(Position p) { ret ticker(p.openingTime); }
65  
66  
  // all "profit" functions return a positive or negative percent value
67  
  real profit(Position p, real time, Market m) {
68  
    ret (ticker(time)/openingPrice(p)*100-100)*p.direction - m.adversity;
69  
  }
70  
71  
  Real closingTime(Position p, Juicer j, Market m) {
72  
    int time = iceil(p.openingTime);
73  
    real openingPrice = ticker(time);
74  
    real crest = -infinity();
75  
    while (time < ticker.length-1) {
76  
      real profit = profit(p, time, m);
77  
      crest = max(crest, profit);
78  
      if (profit < (profit < 0 ? -j.lossTolerance : crest-j.pullback))
79  
        ret (real) time;
80  
      ++time;
81  
    }
82  
    null;
83  
  }
84  
85  
  Real profit(Position p, Juicer j, Market m) {
86  
    Real closingTime = closingTime(p, j, m);
87  
    ret closingTime == null ? null : profit(p, closingTime, m);
88  
  }
89  
90  
  // How profitable is it to open a position of any direction
91  
  // at a certain point in time?
92  
  Real profitability(real time, Juicer j, Market m) {
93  
    ret maxAllowingNull(
94  
      profit(new Position(time, -1), j, m), 
95  
      profit(new Position(time,  1), j, m));
96  
  }
97  
  
98  
  // eye can be null, then we just test the juicer
99  
  record noeq Backtest(Eye eye, Juicer j, Market m) extends Convergent<Real> {
100  
    Iterator<Int> openingTimes = new WeightlessShuffledIterator<Int>(intRangeList(ticker.length));
101  
    
102  
    new Average profitPerPosition;
103  
    // TODO new Average averageHoldTime;
104  
    new Average positionsOpenedPercentage;
105  
    
106  
    // percentage of positions closed before reaching the end of the ticker "tape"
107  
    new Average positionsClosedPercentage;
108  
    
109  
    new L<ClosedPosition> closedPositions;
110  
    
111  
    *(Juicer *j, Market *m) {}
112  
    
113  
    // internal, don't call from outside. Use Convergent/Iterator methods
114  
    void step {
115  
      if (!openingTimes.hasNext())
116  
        ret with done = true;
117  
        
118  
      int openingTime = openingTimes.next();
119  
      
120  
      Real profit = null;
121  
      ClosedPosition closedPosition = null;
122  
      
123  
      if (eye == null) // Test only juicer
124  
        profit = profitability(openingTime, j, m);
125  
      else {
126  
        // Test eye + juicer
127  
        real direction = eye.adviseDirection(new Ticker(ticker, timestamps, openingTime, timestamps[openingTime]));
128  
        positionsOpenedPercentage.addSample(direction != 0 ? 100 : 0);
129  
        if (direction != 0) {
130  
          Position position = new Position(openingTime, direction);
131  
          Real closingTime = closingTime(position, j, m);
132  
          if (closingTime != null) {
133  
            profit = profit(position, closingTime, m);
134  
            closedPosition = new ClosedPosition(position, closingTime).ticker(ticker()).profit(profit);
135  
            closedPositions.add(closedPosition);
136  
          }
137  
        }
138  
      }
139  
      
140  
      positionsClosedPercentage.addSample(profit != null ? 100 : 0);
141  
      if (profit != null) {
142  
        profitPerPosition.addSample(profit);
143  
        //averageHoldTime.addSample(TODO);
144  
      } else // Profit for unclosed positions = 0
145  
        profitPerPosition.addSample(0);
146  
      value = profitPerPosition!;
147  
    }
148  
  }
149  
}

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1036148
Snippet name: MPM2 - Trading Bot v2
Eternal ID of this version: #1036148/72
Text MD5: 013c41bc0ed1e77ae089892172dc2d5a
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-04 13:46:26
Source code size: 5250 bytes / 149 lines
Pitched / IR pitched: No / No
Views / Downloads: 214 / 641
Version history: 71 change(s)
Referenced in: [show references]