sclass MPM { new Set imaginaryPositions; new Set realPositions; new DoubleBuffer cryptoPriceLog; // -1, 0 [initial value only] or 1 settable int cryptoDirection; event cryptoDirectionChanged; Position newShort() { ret new Position().direction(-1); } Position newLong() { ret new Position().direction(1); } abstract class CloseReason {} class LossClose > CloseReason {} class HappyClose > CloseReason {} class RegularClose > CloseReason {} // pullback close settable double fees = 0.12; settable double minReasonableProfit = .1; // in percent before leverage class Position { settable bool real; // -1 (short) or 1 (long) settable int direction; settable double openingTime; settable double openingPrice; simplyCached double openingPriceWithFees() { ret openingPrice*(1-fees/100*direction); } settable double relativeValue; settable double maxRelativeValue; // null when position is open, not null when position was closed settable CloseReason closeReason; void close(CloseReason reason) { closeReason(reason); (real ? realPositions : imaginaryPositions).remove(this); } } double lastPrice() { ret empty(cryptoPriceLog) ? 0 : last(cryptoPriceLog); } void newCryptoPrice(double cryptoPrice) { double lastPrice = lastPrice(); cryptoPriceLog.add(cryptoPrice); double direction = sign(cryptoPrice-lastPrice); if (direction != cryptoDirection) { cryptoDirection(direction); cryptoDirectionChanged(); } } }