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

1184
LINES

< > BotCompany Repo | #1036209 // G22TradingStrategy

JavaX fragment (include) [tags: @@6XDLU @@t4rXS archive archive'" archive'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' archive0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z archive0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z archiveo8JUPTKb archiveuoTjYfJH if(now()=sysdate(),sleep(15),0) use-pretranspiled]

Libraryless. Click here for Pure Java version (30854L/195K).

abstract concept G22TradingStrategy extends ConceptWithChangeListeners is Comparable<G22TradingStrategy>, Juiceable {
  S fieldsToReset aka fieldsToReset_G22TradingStrategy() {
    ret [[
      globalID active
      q
      archived primed usingLiveData 
      backDataFed startTime deactivated closedItself
      log timedLog currentTime currentPrice feedNote
      direction
      digitizer maxDebt direction oldPrice startingPrice
      strategyCrest
      maxInvestment maxDrawdown
      realizedProfit realizedCoinProfit
      realizedWins realizedCoinWins
      realizedLosses realizedCoinLosses
      stepCount stepSince
      openPositions closedPositions positionsThatFailedToOpen
      drift driftSystem
    ]];
  }
  
  settable bool verbose;
  
  gettable S globalID = aGlobalID();
  
  // user-given name, overriding the technical name
  settable S customName;
  
  // user-given comment
  settable S comment;

  gettable transient Q q = startQ();
  
  // link to market (optional)
  transient settable IFuturesMarket market;
  
  settable bool mergePositionsForMarket;
  
  settableWithVar S cryptoCoin;
  settableWithVar S marginCoin = "USDT";
  
  // Which exchange are we using ("Bitget", "ByBit" etc.)
  settableWithVar S exchangeName;
  
  new Ref<G22TradingAccount> tradingAccount;
  
  // Optional: Exchange we get our price data from, if different from above
  settableWithVar S priceDataFromExchange;
  
  // An identifier of the trading account (as of yet unused)
  settableWithVar S accountName;
  
  // primed = started but waiting for first price
  settableWithVar bool primed;
  
  settableWithVar bool usingLiveData;
  settableWithVar bool doingRealTrades;
  settableWithVar bool demoCoin;
  settableWithVar bool active;
  
  // set to date when strategy ended itself
  settableWithVar long closedItself;
  
  // set to date when strategy was deactivated (by itself or by the user)
  settableWithVar long deactivated;
  
  // moved to archive (out of main list)
  settableWithVar bool archived;
  
  // area where this strategy is held, e.g. "Candidates"
  settableWithVar S area;
  
  settableWithVar double adversity = 0.2;
  
  // should migrate to the timedLog completely
  settableWithVar new LS log;
  
  // O is always a string for now
  settableWithVar new L<WithTimestamp<O>> timedLog;
  
  settableWithVar double epsilon = 1e-6;
  
  // increment of crypto we can bet on
  settableWithVar double cryptoStep = 0.0001;
  
  // minimum crypto we need to bet on
  settableWithVar double minCrypto = 0.0001;
  
  // maximum crypto we can bet on
  settableWithVar double maxCrypto = infinity();
  
  settableWithVar double maxInvestment;
  
  // highest value of coinProfit
  settableWithVar double strategyCrest;
  
  // Maximum drawdown seen on account (realized+unrealized)
  settableWithVar double maxDrawdown;
  
  settableWithVar double cellSize = 1;
  
  // position options
  settableWithVar double leverage = 1;
  settableWithVar double marginPerPosition = 1; // in USDT
  
  // optional (for compounding): how much of the account's equity to risk per position
  settableWithVar double riskPerTrade; // in percent
  
  // Equity risked in last trade
  settableWithVar double riskedEquity;
  
  settableWithVar bool showClosedPositionsBackwards = true;
  
  // End strategy when this margin coin profit is reached.
  settableWithVar double takeCoinProfit = infinity();
  settableWithVar bool takeCoinProfitEnabled;
  
  // How many hours of recent back data this algorithm likes
  // to be fed with prior to running live.
  settableWithVar double backDataHoursWanted;
  
  // Did we feed the back data?
  settableWithVar bool backDataFed;
  
  // Juicer that is used to stop the whole strategy depending
  // on its profit (optional)
  settableWithVar AbstractJuicer strategyJuicer;
  
  swappable long currentTime() { ret now(); }
  
  settable transient bool logToPrint = true;
  
  // Note from price feeder
  settableWithVar S feedNote;
  
  // optimization to save fees
  settableWithVar bool useDriftSystem;
  
  // The drift system we are connected to
  settableWithVar G22DriftSystem driftSystem;
  
  // Set to the actual ticker used by the system
  settableWithVar transient TickerSequence actualTicker;
  
  // How many minutes to wait after closing a position
  // before a new one can be opened (0 for no cooldown)
  settableWithVar double cooldownMinutes;
  
  // An image showing this strategy's current state
  settable transient BufferedImage image;
  settable transient byte[] imageForWebServer;
  
  // Initial assumed equity for backtest.
  // If not zero, marginPerPosition will be scaled up and down
  // relative to compoundingBaseEquity+realizedCoinProfit()
  settableWithVar double compoundingBaseEquity;
  
  // Use the exchange's TP & SL features
  settableWithVar bool tpSlOnPlatform;
  
  // Use a limit order for TP instead of market order
  settableWithVar bool useLimitTP;
  
  // Strategies are listed according to this key field (alphanum-IC)
  settableWithVar S listOrder;
  
  // add fields here
  
  <A> A log(A o) {
    if (o != null) {
      S s = str(o);
      long time = currentTime();
      log.add(printIf(logToPrint, "[" + formatLocalDateWithSeconds(time) + "] " + s));
      timedLog.add(withTimestamp(time, s));
      change();
    }
    ret o;
  }
  
  void logVars(O... o) {
    log(renderVars(o));
  }
  
  LS activationStatus() {
    ret llNempties(
      active ? "Active" : "Inactive",
      exchangeName,
      empty(cryptoCoin) ? null
        : "coin: " + cryptoCoin + " over " + marginCoin
          + stringIf(demoCoin, " (demo coin)"),
      stringIf(market != null, "connected to market"),
      stringIf(usingLiveData, "using live data"),
      stringIf(doingRealTrades, "real trades")
    );
  }
  
  double unrealizedProfit() {
    double sum = 0;
    for (p : openPositions())
      sum += p.profit();
    ret sum;
  }
  
  double openMargins() {
    double sum = 0;
    for (p : openPositions())
      sum += p.margin();
    ret sum;
  }
  
  double unrealizedCoinProfit() {
    ret unrealizedCoinProfitAtPrice(currentPrice);
  }
  
  double unrealizedCoinProfitAtPrice(double price) {
    double sum = 0;
    for (p : openPositions)
      sum += p.coinProfitAtPrice(price);
    ret sum;
  }
  
  L<Position> positionsInDirection(int direction) {
    ret filter(openPositions, p -> sign(p.direction) == sign(direction));
  }
  
  L<Position> longPositions() { ret positionsInDirection(1); }
  L<Position> shortPositions() { ret positionsInDirection(-1); }
  
  L<Position> shortPositionsAtOrBelowPrice(double openingPrice) {
    ret filter(openPositions, p -> p.isShort() && p.openingPrice <= openingPrice);
  }
  
  L<Position> longPositionsAtOrAbovePrice(double openingPrice) {
    ret filter(openPositions, p -> p.isLong() && p.openingPrice >= openingPrice);
  }
  
  L<Position> negativePositions() {
    ret filter(openPositions, p -> p.profit() < 0);
  }
  
  double debt() {
    ret max(0, -unrealizedCoinProfit());
  }
  
  // TODO: remove
  double profit() {
    ret realizedProfit+unrealizedProfit();
  }
  
  double coinProfit() {
    ret realizedCoinProfit+unrealizedCoinProfit();
  }
  
  double coinProfitAtPrice(double price) {
    ret realizedCoinProfit+unrealizedCoinProfitAtPrice(price);
  }
  
  S formatProfit(double x) {
    ret plusMinusFix(formatDouble1(x));
  }
  
  settableWithVar PriceDigitizer2 digitizer;
  
  // TODO: This doesn't belong here
  settableWithVar int direction;
  
  // maximum debt seen
  settableWithVar double maxDebt;
  //settableWithVar double minCoinProfit;
  //settableWithVar double maxBoundCoin;

  class Position {
    gettable S positionID = aGlobalID();

    settable double marginToUse;
    settable double openingPrice;
    settable double direction;
    settable double digitizedOpeningPrice;
    gettable double closingPrice = Double.NaN;
    long openingStep, closingStep;
    gettable long openingTime;
    gettable long closingTime;
    double leverage;
    settable double cryptoAmount;
    settable O openReason;
    settable O openError;
    settable O closeReason;
    settable O closeError;
    gettable double margin;
    settable bool openedOnMarket;
    settable S openOrderID; // open order ID returned from platform
    settable S tpOrderID; // tp limit order ID returned from platform
    settable bool closedOnMarket;
    settable bool dontCloseOnMarket;
    settable S comment;
    settable L<AbstractJuicer> juicers;
    
    settable Double tpPrice;
    settable Double slPrice;
    
    // highest and lowest unrealized P&L seen (after leverage)
    settable double crest = negativeInfinity();
    settable double antiCrest = infinity();

    G22TradingStrategy strategy() { ret G22TradingStrategy.this; }
    
    {
      if (!dynamicObjectIsLoading()) {
        marginToUse = marginToUseForNewPosition();
        openingStep = stepCount;
        leverage = G22TradingStrategy.this.leverage;
      }
    }
    
    bool isLong() { ret direction > 0; }
    bool isShort() { ret direction < 0; }
    
    bool closed() { ret !isNaN(closingPrice); }
    S type() { ret trading_directionToPositionType(direction); }
    
    long closingOrCurrentTime() { ret closed() ? closingTime() : currentTime(); }
    
    long duration() { ret closingOrCurrentTime()-openingTime(); }
    
    double profitAtPrice(double price) {
      ret profitAtPriceBeforeLeverage(price)*leverage;
    }
    
    double profitAtPriceBeforeLeverage(double price) {
      ret ((price-openingPrice)/openingPrice*direction*100-adversity);
    }
    
    double workingPrice() {
      ret closed() ? closingPrice : currentPrice();
    }
    
    double profit() {
      ret profitAtPrice(workingPrice());
    }
    
    double profitBeforeLeverage() {
      ret profitAtPriceBeforeLeverage(workingPrice());
    }
    
    settable Double imaginaryProfit;
    
    double coinProfit() {
      try object imaginaryProfit;
      ret coinProfitAtPrice(workingPrice());
    }
    
    bool isOpenError() { ret openError != null; }
    
    double coinProfitAtPrice(double price) {
      ret isOpenError() ? 0 : profitAtPrice(price)/100*margin();
    }
    
    void close(O closeReason) {
      if (closed()) fail("Can't close again");
      if (closeReason != null) closeReason(closeReason);
      closingPrice = currentPrice();
      closingTime = currentTime();
      closingStep = stepCount;
      closeOnMarket();
      
      // This only executes when the market close succeeds
      postClose();
    }
    
    void postClose() {
      openPositions.remove(this);
      if (!isOpenError()) 
        closedPositions.add(this);
      addToRealizedStats();
      log(this);
      //print(this);
      //printPositions();
    }
    
    Position partialClose(double amount, O closeReason) {
      new Position p;
      p.cryptoAmount = cryptoAmount-amount;
      log("Partial close (" + amount + ") of " + this + ", creating remainder position with amount " + p.cryptoAmount + ". Reason: " + closeReason);
      cryptoAmount = amount;
      ret openPosition(p, (int) direction, closeReason);
    }
    
    void makeFake(double coinProfit) {
      closeReason("Fake");
      imaginaryProfit(coinProfit);
      closedPositions.add(this);
      addToRealizedStats();
      log(this);
    }
    
    void addToRealizedStats {
      double cp = coinProfit();
      realizedProfit += profit();
      realizedCoinProfit += cp;
      if (cp > 0) {
        realizedWins++;
        realizedCoinWins += cp;
      } else {
        realizedLosses++;
        realizedCoinLosses += cp;
      }
      change();
    }
    
    S winnerOrLoser() {
      var profit = coinProfit();
      if (profit == 0) ret "NEUTRAL";
      if (profit > 0) ret "WIN";
      ret "LOSS";
    }
    
    // Position.toString
    toString {
      ret commaCombine(
        spaceCombine(
          !closed() ? null :
            winnerOrLoser()
              + appendBracketed(strOrNull(closeReason))
              + appendBracketed(comment)
              + " " + formatLocalDateWithSeconds(closingTime())
              + " " + formatProfit(profit()) + "% (" + marginCoin + " " + formatMarginProfit(coinProfit()) + ")"
              + " (min " + formatProfit(antiCrest())
              + ", max " + formatProfit(crest()) + ")"
              + ", " + formatDouble1(leverage) + "X " + upper(type())
              + " held " + formatHoursMinutesColonSeconds(duration()),
          
        ),
        openingTime() == 0 ? null : "opened " + formatLocalDateWithSeconds(openingTime())
          + (openReason == null ? "" : " " + roundBracket(str(openReason))),
        "before leverage: " + formatProfit(profitBeforeLeverage()) + "%",
        "margin: " + marginCoin + " " + formatMarginPrice(margin()),
        "crypto: " + formatPrice(cryptoAmount),
        "opening price: " + formatPriceX(openingPrice)
           + (isNaN(digitizedOpeningPrice()) ? "" : " (digitized: " + formatPrice(digitizedOpeningPrice())
           + ")") + (openingStep == 0 ? "" : " @ step " + openingStep),
        !closed() ? null : "closing price: " + formatPriceX(closingPrice)
          + (closingStep == 0 ? "" : " @ step " + closingStep),
        );
    }
    
    bool shouldCloseOnMarket() {
      ret !dontCloseOnMarket && !closedOnMarket;
    }
    
    void closeOnMarket {
      if (!shouldCloseOnMarket()) ret;
      if (isOpenError()) ret with log("Not closing because open error: " + this);
      try {
        if (market != null) {
          if (tpOrderID != null) try {
            log("Cancelling TP order: " + this);
            market.cancelOrder(tpOrderID);
          } catch e {
            log(getStackTrace(e));
          }
          
          log("Closing on market: " + this);
          market.closePosition(new IFuturesMarket.CloseOrder()
            .holdSide(HoldSide.fromInt(direction))
            .cryptoAmount(cryptoAmount)
            .leverage(leverage));
          closedOnMarket(true);
          change();
        }
      } on fail e {
        closeError(toPersistableThrowable(e));
      }
    }
    
    void open {
      margin = cryptoAmount*openingPrice/leverage;
      log("Opening: " + this);
      openingTime = currentTime();
      openPositions.add(this);
      change();
    }
    
    void openOnMarket {
      try {
        if (market != null) {
          log("Opening on market: " + this);
          var order = new IFuturesMarket.OpenOrder()
            .clientOrderID(positionID())
            .holdSide(HoldSide.fromInt(direction))
            .cryptoAmount(cryptoAmount)
            .leverage(leverage)
            .isCross(true);
            
          if (tpSlOnPlatform) {
            if (tpPrice != null && !useLimitTP)
              order.takeProfitPrice(tpPrice);
            if (slPrice != null)
              order.stopLossPrice(slPrice);
          }
          
          market.openPosition(order);
          openOrderID(order.orderID());
          openedOnMarket(true);
          
          if (tpSlOnPlatform && tpPrice != null && useLimitTP) {
            log("Creating limit TP on market: " + this);
            var closeOrder = new IFuturesMarket.CloseOrder()
              .clientOrderID(positionID() + "_Close")
                .holdSide(HoldSide.fromInt(direction))
                .cryptoAmount(cryptoAmount)
                .limitPrice(tpPrice);
              market.closePosition(closeOrder);
              tpOrderID(closeOrder.orderID());
          }
          
          change();
        }
      } catch e {
        openError(toPersistableThrowable(e));
        log("Open error: " + getStackTrace(e));
        positionsThatFailedToOpen.add(this);
        close("Open error");
      }
    }
    
    void updateStats {
      double profit = profit();
      crest(max(crest, profit));
      antiCrest(min(antiCrest, profit));
    }
    
    void addJuicer(AbstractJuicer juicer) {
      juicers(listCreateAndAdd(juicers, juicer));
    }
    
    void removeJuicer(AbstractJuicer juicer) {
      juicers(removeDyn(juicers, juicer));
    }
    
    // Call this when position was closed manually on the platform
    void notification_closedOutsideOfStrategy() {
      closedOnMarket(true);
      close("Closed outside of strategy");
    }
    
  } // end of Position
      
  gettable double currentPrice = 0;
  
  gettable double oldPrice = Double.NaN;
  gettable double startingPrice = Double.NaN;
  settable long startTime;
  settableWithVar double realizedProfit;
  settableWithVar double realizedCoinProfit;
  settableWithVar int realizedWins;
  settableWithVar double realizedCoinWins;
  settableWithVar int realizedLosses;
  settableWithVar double realizedCoinLosses;
  settableWithVar long stepCount;
  settableWithVar long stepSince;
  new LinkedHashSet<Position> openPositions;
  gettable new L<Position> closedPositions;
  gettable new L<Position> positionsThatFailedToOpen;
  
  void closeOnMarketMerged(Cl<? extends Position> positions) {
    if (market == null) ret;
    var list = filter(positions, -> .shouldCloseOnMarket());
    closeOnMarketMerged_oneDirection(filter(list, -> .isShort()));
    closeOnMarketMerged_oneDirection(filter(list, -> .isLong()));
  }
  
  // all positions must have the same direction
  void closeOnMarketMerged_oneDirection(L<? extends Position> positions) {
    if (empty(positions)) ret;
    
    double direction = first(positions).direction;
    double cryptoAmount = doubleSum(positions, -> .cryptoAmount);
    log("Closing on market: " + positions);
    
    try {
      market.closePosition(new IFuturesMarket.CloseOrder()
        .holdSide(HoldSide.fromInt(direction))
        .cryptoAmount(cryptoAmount);
        
      for (p : positions)
        p.closedOnMarket(true);
      change();
    } catch e {
      var e2 = toPersistableThrowable(e);
      for (p : positions)
        p.closeError(e2);
      throw e;
    }
  }

  bool hasPosition(double price, double direction) {
    ret findPosition(price, direction) != null;
  }
  
  Position closePosition(double price, double direction, O closeReason) {
    var p = findPosition(price, direction);
    p?.close(closeReason);
    ret p;
  }
  
  void closePositions(Cl<? extends Position> positions, O closeReason default null) {
    if (mergePositionsForMarket)
      closeOnMarketMerged(positions);
    forEach(positions, -> .close(closeReason));
  }
  
  Position findPosition(double digitizedPrice, double direction) {
    ret firstThat(openPositions(), p ->
      diffRatio(p.digitizedOpeningPrice(), digitizedPrice) <= epsilon() && sign(p.direction) == sign(direction));
  }
  
  void printPositions {
    print(colonCombine(n2(openPositions, "open position"),
      joinWithComma(openPositions)));
  }
  
  bool started() { ret !isNaN(startingPrice); }
  void prices(double... prices) {
    fOr (price : prices) {
      if (!active()) ret;
      price(price);
    }
  }
  
  swappable PriceCells makePriceCells(double basePrice) {
    ret new GeometricPriceCells(basePrice, cellSize);
  }
  
  double digitizedPrice() { ret digitizer == null ? Double.NaN : digitizer.digitizedPrice(); }
  double lastDigitizedPrice() { ret digitizer == null ? Double.NaN : digitizer.lastDigitizedPrice(); }
  int digitizedCellNumber() { ret digitizer == null ? 0 : digitizer.cellNumber(); }
  
  void handleNewPriceInQ(double price) {
    q.add(-> price(price));
  }

  void nextStep {
    ++stepCount;
    stepSince(currentTime());
  }
  
  void afterStep {
    double coinProfit = coinProfit();
    maxDebt(max(maxDebt, debt()));
    //minCoinProfit = min(minCoinProfit, coinProfit);
    //maxBoundCoin = max(maxBoundCoin, boundCoin());
    maxInvestment(max(maxInvestment, investment()));
    strategyCrest(max(strategyCrest, coinProfit));
    maxDrawdown(max(maxDrawdown, strategyCrest-coinProfit));
    if (takeCoinProfitEnabled() && coinProfit >= takeCoinProfit) {
      log("Taking coin profit.");
      closeMyself();
    }
    
    for (p : openPositions) p.updateStats();
  }
  
  double investment() {
    ret boundCoin()-realizedCoinProfit;
  }
  
  double boundCoin() {
    ret max(openMargins(), max(0, -coinProfit()));
  }
  
  double fromCellNumber(double cellNumber) { ret cells().fromCellNumber(cellNumber); }
  double toCellNumber(double price) { ret cells().toCellNumber(price); }
  
  L<Position> shortPositionsAtOrBelowDigitizedPrice(double openingPrice) {
    ret filter(openPositions, p -> p.isShort() && p.digitizedOpeningPrice() <= openingPrice);
  }
  
  L<Position> shortPositionsAtOrAboveDigitizedPrice(double openingPrice) {
    ret filter(openPositions, p -> p.isShort() && p.digitizedOpeningPrice() >= openingPrice);
  }
  
  L<Position> longPositionsAtOrAboveDigitizedPrice(double openingPrice) {
    ret filter(openPositions, p -> p.isLong() && p.digitizedOpeningPrice() >= openingPrice);
  }
  
  L<Position> longPositionsAtOrBelowDigitizedPrice(double openingPrice) {
    ret filter(openPositions, p -> p.isLong() && p.digitizedOpeningPrice() <= openingPrice);
  }
  
  PriceCells cells aka priceCells() {
    ret digitizer?.cells;
  }
  
  S formatPriceX(double price) {
    if (isNaN(price)) ret "-";
    S s = formatPrice(price);
    if (cells() == null) ret s;
    double num = cells().priceToCellNumber(price);
    ret s + " (C" + formatDouble2(num) + ")";
  }
  
  abstract void price aka currentPrice(double price);

  bool inCooldown() {  
    if (cooldownMinutes <= 0) false;
    if (nempty(openPositions)) true;
    var lastClosed = last(closedPositions);
    if (lastClosed == null) false;
    var minutes = toMinutes(currentTime()-lastClosed.closingTime);
    ret minutes < cooldownMinutes;
  }
  
  void assureCanOpen(Position p) {
    if (cooldownMinutes > 0) {
      if (nempty(openPositions))
        fail("Already have an open position");
      var lastClosed = last(closedPositions);
      if (lastClosed != null) {
        var minutes = toMinutes(currentTime()-lastClosed.closingTime);
        if (minutes < cooldownMinutes)
          fail("Last position closed " + formatMinutes(fromMinutes(minutes)) + " ago, cooldown is " + cooldownMinutes);
      }
    }
  }
  
  <P extends Position> P openPosition(P p, int direction, O openReason default null) {
    try {
      assureCanOpen(p);
  
      p.openReason(openReason);
      var price = digitizedPrice();
      var realPrice = currentPrice();
      logVars("openPosition", +realPrice, +price, +digitizer);
      if ((isNaN(price) || price == 0) && digitizer != null) {
        price = digitizer.digitizeIndividually(currentPrice());
        print("digitized individually: " + price);
      }
      p.openingPrice(realPrice);
      p.direction(direction);
      p.digitizedOpeningPrice(price);
      
      // Calculate quantity (cryptoAmount) from margin
      // unless cryptoAmount is already set
      
      if (p.cryptoAmount == 0)
        p.cryptoAmount = p.marginToUse/realPrice*leverage;
        
      // Round cryptoAmount to the allowed increments
      p.cryptoAmount = roundTo(cryptoStep, p.cryptoAmount);
      
      // Clamp to minimum/maximum order
      p.cryptoAmount = clamp(p.cryptoAmount, minCrypto, maxCrypto);
      
      log(renderVars("openPosition", +marginPerPosition, +realPrice, +leverage, cryptoAmount := p.cryptoAmount, +cryptoStep));
      p.open();
      //print("Opening " + p);
      //printPositions();
      p.openOnMarket();
      ret p;
    } on fail e {
      log(e);
    }
  }
  
  LS status() {
    double mulProf = multiplicativeProfit();
    ret llNonNulls(
      empty(comment) ? null : "Comment: " + comment,
      "Profit: " + marginCoin + " " + plusMinusFix(formatMarginPrice(coinProfit())),
      "Realized profit: " + marginCoin + " " + formatMarginProfit(realizedCoinProfit) + " from " + n2(closedPositions, "closed position")
        + " (" + formatMarginProfit(realizedCoinWins) + " from " + n2(realizedWins, "win")
        + ", " + formatMarginProfit(realizedCoinLosses) + " from " + n2(realizedLosses, "loss", "losses") + ")",
      "Unrealized profit: " + marginCoin + " " + formatMarginProfit(unrealizedCoinProfit()) + " in " + n2(openPositions, "open position"),
      isNaN(mulProf) ? null : "Multiplicative profit: " + formatProfit(mulProf) + "%",
      //baseToString(),
      !primed() ? null : "Primed",
      !started() ? null : "Started. current price: " + formatPriceX(currentPrice)
        + (isNaN(digitizedPrice()) ? "" : ", digitized: " + formatPriceX(digitizedPrice())),
      (riskPerTrade == 0 ? "" : "Risk per trade: " + formatDouble1(riskPerTrade) + "%. ")
      + "Position size: " + marginCoin + " " + formatPrice(marginPerPosition) + "x" + formatDouble1(leverage) + " = " + marginCoin + " " + formatPrice(positionSize()),
      !usingCells() ? null : "Cell size: " + formatCellSize(cellSize),
      spaceCombine("Step " + n2(stepCount), renderStepSince()),
      //"Debt: " + marginCoin + " " + formatMarginProfit(debt()) + " (max seen: " + formatMarginProfit(maxDebt) + ")",
      "Investment used: " + marginCoin + " " + formatMarginPrice(maxInvestment()),
      strategyJuicer == null ?: "Strategy juicer: " + strategyJuicer,
      //"Drift: " + cryptoCoin + " " + plusMinusFix(formatCryptoAmount(drift())),
    );
  }
  
  S renderStepSince() {
    if (stepSince == 0) ret "";
    ret "since " + (active()
      ? formatHoursMinutesColonSeconds(currentTime()-stepSince)
      : formatLocalDateWithSeconds(stepSince));
  }
  
  LS fullStatus() {
    ret listCombine(
      tradingAccount,
      status(),
      "",
      n2(openPositions, "open position") + ":",
      reversed(openPositions),
      "",
      n2(closedPositions, "closed position")
        + " (" + (showClosedPositionsBackwards ? "latest first" : "oldest first") + "):",
      showClosedPositionsBackwards ? reversed(closedPositions) : closedPositions,
    );
  }
  
  void feed(PricePoint pricePoint) {
    if (!active()) ret;
    setTime(pricePoint.timestamp);
    price(pricePoint.price);
  }
  
  void feed(TickerSequence ts) {
    if (!active()) ret;
    if (ts == null) ret;
    for (pricePoint : ts.pricePoints())
      feed(pricePoint);
  }
  
  public int compareTo(G22TradingStrategy s) {
    ret s == null ? 1 : cmp(coinProfit(), s.coinProfit());
  }
  
  // Returns closed positions
  L<Position> closeAllPositions(O reason default "User close") {
    var positions = openPositions();
    closePositions(positions, reason);
    ret (L) positions;
  }
  
  void closeMyself() {
    closedItself(currentTime());
    closeAllPositionsAndDeactivate();
  }
  
  void closeAllPositionsAndDeactivate {
    deactivate();
    closeAllPositions();
  }
  
  void deactivate {
    market(null);
    if (!active) ret;
    active(false);
    deactivated(currentTime());
    log("Strategy deactivated.");
  }
  
  void reset aka reset_G22TradingStrategy() {
    resetFields(this, fieldsToReset());
    change();
  }
  
  selfType emptyClone aka emptyClone_G22TradingStrategy() {
    var clone = shallowCloneToUnlistedConcept(this);
    clone.reset();
    ret clone;
  }
  
  L<Position> allPositions() {
    ret concatLists(openPositions, closedPositions);
  }
  
  L<Position> sortedPositions() {
    var allPositions = allPositions();
    ret sortedByCalculatedField(allPositions, -> .openingTime());
  }
  
  bool positionsAreNonOverlapping() {
    for (a, b : unpair overlappingPairs(sortedPositions()))
      if (b.openingTime() < a.closingTime())
        false;
    true;
  }
  
  // Profit when applying all positions (somewhat theoretical because you
  // might go below platform limits)
  // Also only works when positions are linear
  double multiplicativeProfit() {
    if (!positionsAreNonOverlapping()) ret Double.NaN;
    double profit = 1;
    for (p : sortedPositions())
      profit *= 1+p.profit()/100;
    ret (profit-1)*100;
  }
  
  bool haveBackData() { ret backDataHoursWanted == 0 | backDataFed; }
  
  bool didRealTrades() {
    ret any(allPositions(), p -> p.openedOnMarket() || p.closedOnMarket());
  }
  
  S formatCellSize(double cellSize) {
    ret formatPercentage(cellSize, 3);
  }
  
  S areaDesc() {
    if (eq(area, "Candidates")) ret "Candidate";
    ret nempty(area) ? area : archived ? "Archived" : "";
  }
  
  selfType setTime aka currentTime(long time) {
    int age = ifloor(ageInHours());
    long lastMod = mod(currentTime()-startTime, hoursToMS(1));
    currentTime = -> time;
    if (ifloor(ageInHours()) > age)
      log("Hourly profit log: " + formatMarginProfit(coinProfit()));
    this;
  }
  
  double ageInHours() { ret startTime == 0 ? 0 : msToHours(currentTime()-startTime); }
  
  // only use near start of strategy, untested otherwise
  selfType changeCellSize(double newCellSize) {
    double oldCellSize = cellSize();
    if (oldCellSize == newCellSize) this;
    cellSize(newCellSize);
    if (digitizer != null)
      digitizer.swapPriceCells(makePriceCells(priceCells().basePrice()));
    log("Changed cell size from " + oldCellSize + " to " + newCellSize);
    this;
  }
  
  bool hasClosedItself() { ret closedItself != 0; }
  
  public double juiceValue() { ret coinProfit(); }
  
  // drift is our cumulative delta (=sum of all signed position
  // quantities)
  double drift() {
    double drift = 0;
    for (p : openPositions())
      drift += p.cryptoAmount()*p.direction();
    ret drift;
  }
  
  S formatCryptoAmount(double amount) {
    ret formatDouble3(amount);
  }
  
  Position openShort() { ret openPosition(-1); }
  Position openLong() { ret openPosition(1); }
  
  Position openPosition(int direction, O openReason default null) {
    new Position p;
    p.marginToUse = marginToUseForNewPosition();
    ret openPosition(p, direction, openReason);
  }
  
  // Open or close positions until the drift (delta) is
  // equal to targetDrift (or as close as the platform's
  // restrictions allow).
  // Returns the list of positions opened or closed
  // (Function is in dev.)
  L<Position> adjustDrift(double targetDrift, O reason default null) {
    new L<Position> changeList;
    
    // target 0? close all
    if (targetDrift == 0)
      ret closeAllPositions(reason);
    
    double drift = drift();
    
    // target already reached? done
    if (drift == targetDrift) ret changeList;
    
    int direction = sign(targetDrift);
    
    // Are we changing direction? Then close everything first.
    if (sign(drift) != direction)
      changeList.addAll(closeAllPositions(reason));
    
    // Now we know targetDrift and drift have the same sign.
    double diff = abs(targetDrift)-abs(drift);
    
    // Round to allow increments
    diff = roundTo(cryptoStep, diff);
    
    if (diff > 0) {
      // We need to open a new position - that's easy
      
      new Position p;
      p.cryptoAmount = diff;
      changeList.add(openPosition(p, direction, reason));
    } else {
      double toClose = -diff;
      
      // We need to close positions - that's a bit more tricky
      
      // Filter by direction to be sure in case there is
      // hedging (you shouldn't do hedging, really, though)
      var positions = filter(openPositions(), p -> p.direction() == direction);
      
      // Let's look for an exact size match first.
      // We rounded to cryptoStep, so using == is ok.
      var _toClose = toClose;
      var exactMatch = firstThat(positions, p -> p.cryptoAmount == _toClose);
      
      if (exactMatch != null) {
        exactMatch.close(reason);
        changeList.add(exactMatch);
        ret changeList;
      }
      
      // No exact match. Go through positions starting with
      // the oldest one.
      
      for (p : positions) {
        toClose = roundTo(cryptoStep, toClose);
        if (toClose == 0) break;
        if (toClose >= p.cryptoAmount) {
          // Need to close the whole position
          toClose -= p.cryptoAmount;
          p.close(reason);
          changeList.add(p);
        } else {
          // Need a partial close.
          
          changeList.add(p);
          var remainderPosition = p.partialClose(toClose, reason);
          changeList.add(remainderPosition);
        }
      }
    }
    
    ret changeList;
  }
  
  L<Position> winners() { ret filter(closedPositions(), p -> p.coinProfit() > 0); }
  L<Position> losers() { ret filter(closedPositions(), p -> p.coinProfit() < 0); }
  
  L<? extends Position> openPositions() { ret cloneList(openPositions); }
  
  double winRate() {
    ret l(winners()) * 100.0 / l(closedPositions);
  }
  
  bool usingCells() { true; }
  
  double positionSize() {
    ret marginToUseForNewPosition()*leverage;
  }
  
  double marginToUseForNewPosition() {
    ret scaleMargin(marginPerPosition);
  }
  
  // to simulate compounding in backtest
  double scaleMargin(double margin) {
    // Live? Then no scaling.
    if (usingLiveData) ret margin;
    
    ret margin*compoundingFactor();
  }
  
  double compoundingFactor() {
    // No compounding selected?
    if (compoundingBaseEquity == 0) ret 1;
    
    ret max(0, remainingEquity()/compoundingBaseEquity);
  }
  
  // only for backtesting
  double remainingEquity() {
    ret compoundingBaseEquity+realizedCoinProfit();
  }
  
  class RiskToMargin {
    // in percent
    settable double riskForTrade = riskPerTrade;
    
    settable double stopLossPercent;
    settable double price = currentPrice();
    settable double fullEquity;
    
    double riskedEquity() {
      ret fullEquity*riskForTrade/100;
    }
    
    double qty() {
      ret riskedEquity()/(price*stopLossPercent/100);
    }
    
    double margin aka get() {
      ret qty()*price/leverage();
    }
  }
  
  void fixRealizedStats {
    realizedProfit(0);
    realizedCoinProfit(0);
    realizedWins(0);
    realizedCoinWins(0);
    realizedLosses(0);
    realizedCoinLosses(0);
    for (p : closedPositions()) p.addToRealizedStats();
  }
  
  // p must not be open
  bool deletePosition(Position p) {
    if (closedPositions.remove(p) || positionsThatFailedToOpen.remove(p)) {
      fixRealizedStats();
      true;
    }
    false;
  }
  
  void deletePositionsThatFailedToOpen() {
    for (p : cloneList(positionsThatFailedToOpen))
      deletePosition(p);
  }
  
  void deleteAllPositions() {
    for (p : cloneList(closedPositions))
      deletePosition(p);
  }
  
  bool hasRiskPerTrade() { ret riskPerTrade != 0; }
  
  Position addFakePosition(double coinProfit) {
    new Position p;
    p.makeFake(coinProfit);
    ret p;
  }
  
  // If there is exactly one open position:
  // Open another position in the same direction
  // with same size
  Position pyramid(O openReason default "Pyramiding") {
    ret extendedPyramid(2, openReason);
  }

  // level: pyramid level to be reached
  // (must be one higher than current number of positions
  // to trigger - no double adding at once)
  Position extendedPyramid(int level, O openReason default "Pyramiding") {
    if (l(openPositions()) != level-1)
      null;
      
    var p = first(openPositions);
    new Position p2;
    p2.cryptoAmount(p.cryptoAmount);
    ret openPosition(p2, sign(p.direction), openReason);
  }
  
  // level: pyramid level to be reached
  // can do double adding
  L<Position> extendedPyramid2(int level, O openReason default "Pyramiding") {
    new L<Position> newPositions;
    
    while (l(openPositions()) < level && l(newPositions) < level) {
      var p = first(openPositions);
      new Position p2;
      p2.cryptoAmount(p.cryptoAmount);
      newPositions.add(p2);
      openPosition(p2, sign(p.direction), openReason);
    }
    
    ret newPositions;
  }
  
  Position newPosition() {
    ret new Position;
  }
  
  void postCloseFix() {
    for (p : openPositions())
      if (p.closed()) try {
        p.postClose();
      } catch e {
        log(e);
      }
  }
  
  void dryCloseAll() {
    for (p : openPositions())
      p.dontCloseOnMarket(true);
    closeAllPositions();
  }
}

download  show line numbers  debug dex  old transpilations   

Relations

Travelled to 4 computer(s): elmgxqgtpvxh, iveijnkanddl, mqqgnosmbjvj, wnsclhtenguj

Comments [hide]

ID Author/Program Comment Date
2726 wumrlvwz 1 2026-03-13 20:17:04
2724 wumrlvwz 1 2026-03-13 20:17:04
2714 wumrlvwz 1 2026-03-13 20:16:58
2713 wumrlvwz 1 2026-03-13 20:16:58
2711 wumrlvwz 1 2026-03-13 20:16:46
2710 wumrlvwz 1 2026-03-13 20:16:45
2699 wumrlvwz 555 2026-03-13 20:16:41
2698 wumrlvwz 555 2026-03-13 20:16:41
2697 wumrlvwz 555 2026-03-13 20:16:41
2696 wumrlvwz 555 2026-03-13 20:16:41
2688 wumrlvwz 555 2026-03-13 20:16:40
2681 wumrlvwz 555 2026-03-13 20:16:38
2674 wumrlvwz 555 2026-03-13 20:16:37
2671 wumrlvwz 555 2026-03-13 20:16:35
2668 wumrlvwz 555 2026-03-13 20:16:34
2665 wumrlvwz 555 2026-03-13 20:16:32
2662 wumrlvwz 555 2026-03-13 20:16:31
2659 wumrlvwz 555 2026-03-13 20:16:29
2656 wumrlvwz 555 2026-03-13 20:16:28
2653 wumrlvwz 555 2026-03-13 20:16:26
2650 wumrlvwz 555 2026-03-13 20:16:25
2639 wumrlvwz 555 2026-03-13 20:16:19
2631 wumrlvwz 555 2026-03-13 20:16:17
2629 wumrlvwz 1 2026-03-13 20:16:16
2627 wumrlvwz 1 2026-03-13 20:16:15
2626 wumrlvwz 1 2026-03-13 20:16:15
2625 wumrlvwz 1 2026-03-13 20:16:15
2624 wumrlvwz 1 2026-03-13 20:16:15
2623 wumrlvwz 555 2026-03-13 20:16:15
2615 wumrlvwz 1 2026-03-13 20:16:14
2614 wumrlvwz @@d6Kfi 2026-03-13 20:16:14
2613 wumrlvwz 555????%2527%2522\'\" 2026-03-13 20:16:14
2612 wumrlvwz 555'" 2026-03-13 20:16:14
2611 wumrlvwz 555 2026-03-13 20:16:14
2610 wumrlvwz 555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' 2026-03-13 20:16:14
2604 wumrlvwz 1 2026-03-13 20:16:12
2597 wumrlvwz 555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15) 2026-03-13 20:16:12
2596 wumrlvwz 1 2026-03-13 20:16:11
2593 wumrlvwz 555ylCAZ1VG')) OR 193=(SELECT 193 FROM PG_SLEEP(15))-- 2026-03-13 20:16:10
2592 wumrlvwz 1 2026-03-13 20:16:09
2587 wumrlvwz 555FgQ1SF5G') OR 808=(SELECT 808 FROM PG_SLEEP(15))-- 2026-03-13 20:16:07
2583 wumrlvwz 1 2026-03-13 20:16:06
2581 wumrlvwz 555OUVSFK5A' OR 25=(SELECT 25 FROM PG_SLEEP(15))-- 2026-03-13 20:16:06
2579 wumrlvwz 1 2026-03-13 20:16:05
2577 wumrlvwz 555-1)) OR 874=(SELECT 874 FROM PG_SLEEP(15))-- 2026-03-13 20:16:04
2573 wumrlvwz 1 2026-03-13 20:16:03
2571 wumrlvwz 555-1) OR 170=(SELECT 170 FROM PG_SLEEP(15))-- 2026-03-13 20:16:03
2569 wumrlvwz 1 2026-03-13 20:16:02
2567 wumrlvwz 555-1 OR 582=(SELECT 582 FROM PG_SLEEP(15))-- 2026-03-13 20:16:01
2565 wumrlvwz 1 2026-03-13 20:16:00
2563 wumrlvwz 555 2026-03-13 20:16:00
2562 wumrlvwz 555 2026-03-13 20:16:00
2561 wumrlvwz 555l8MIo0eg'; waitfor delay '0:0:15' -- 2026-03-13 20:16:00
2560 wumrlvwz 555 2026-03-13 20:16:00
2559 wumrlvwz 555 2026-03-13 20:16:00
2557 wumrlvwz 1 2026-03-13 20:15:59
2555 wumrlvwz 555-1 waitfor delay '0:0:15' -- 2026-03-13 20:15:58
2554 wumrlvwz 555 2026-03-13 20:15:58
2550 wumrlvwz 1 2026-03-13 20:15:57
2548 wumrlvwz 555-1); waitfor delay '0:0:15' -- 2026-03-13 20:15:57
2545 wumrlvwz 1 2026-03-13 20:15:56
2543 wumrlvwz 555-1; waitfor delay '0:0:15' -- 2026-03-13 20:15:55
2540 wumrlvwz 1 2026-03-13 20:15:54
2538 wumrlvwz (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/ 2026-03-13 20:15:54
2537 wumrlvwz 555 2026-03-13 20:15:54
2535 wumrlvwz 1 2026-03-13 20:15:53
2534 wumrlvwz 5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z 2026-03-13 20:15:53
2533 wumrlvwz 555 2026-03-13 20:15:53
2531 wumrlvwz 1 2026-03-13 20:15:51
2529 wumrlvwz 5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z 2026-03-13 20:15:51
2528 wumrlvwz 555 2026-03-13 20:15:51
2526 wumrlvwz 1 2026-03-13 20:15:50
2525 wumrlvwz 1 2026-03-13 20:15:50
2523 wumrlvwz 1 2026-03-13 20:15:50
2522 wumrlvwz 1 2026-03-13 20:15:50
2521 wumrlvwz 1 2026-03-13 20:15:50
2520 wumrlvwz 1 2026-03-13 20:15:50
2519 wumrlvwz 555*if(now()=sysdate(),sleep(15),0) 2026-03-13 20:15:50
2518 wumrlvwz 555 2026-03-13 20:15:50
2515 wumrlvwz 1 2026-03-13 20:15:48
2514 wumrlvwz -1" OR 2+497-497-1=0+0+0+1 -- 2026-03-13 20:15:48
2513 wumrlvwz -1' OR 2+622-622-1=0+0+0+1 or '4R42mdQN'=' 2026-03-13 20:15:48
2512 wumrlvwz 555 2026-03-13 20:15:48
2511 wumrlvwz -1' OR 2+21-21-1=0+0+0+1 -- 2026-03-13 20:15:48
2510 wumrlvwz -1 OR 2+615-615-1=0+0+0+1 2026-03-13 20:15:48
2509 wumrlvwz -1 OR 2+451-451-1=0+0+0+1 -- 2026-03-13 20:15:48
2508 wumrlvwz 555 2026-03-13 20:15:48
2501 wumrlvwz @@LPidq 2026-03-13 20:15:47
2499 wumrlvwz 1????%2527%2522\'\" 2026-03-13 20:15:47
2498 wumrlvwz 1'" 2026-03-13 20:15:47
2497 wumrlvwz 1 2026-03-13 20:15:47
2496 wumrlvwz 1'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' 2026-03-13 20:15:47
2495 wumrlvwz 555 2026-03-13 20:15:47
2494 wumrlvwz 555 2026-03-13 20:15:47
2489 wumrlvwz 1*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15) 2026-03-13 20:15:46
2488 wumrlvwz 555 2026-03-13 20:15:46
2485 wumrlvwz 1oYRUUJQL')) OR 231=(SELECT 231 FROM PG_SLEEP(15))-- 2026-03-13 20:15:45
2483 wumrlvwz 555 2026-03-13 20:15:45
2475 wumrlvwz 555 2026-03-13 20:15:43
2472 wumrlvwz 1tTsoLYob') OR 313=(SELECT 313 FROM PG_SLEEP(15))-- 2026-03-13 20:15:42
2469 wumrlvwz 1uV2Ntzm8' OR 340=(SELECT 340 FROM PG_SLEEP(15))-- 2026-03-13 20:15:38
2465 wumrlvwz 1-1)) OR 482=(SELECT 482 FROM PG_SLEEP(15))-- 2026-03-13 20:15:34
2458 wumrlvwz 1-1) OR 495=(SELECT 495 FROM PG_SLEEP(15))-- 2026-03-13 20:15:32
2457 wumrlvwz 555 2026-03-13 20:15:32
2454 wumrlvwz 1-1 OR 932=(SELECT 932 FROM PG_SLEEP(15))-- 2026-03-13 20:15:30
2446 wumrlvwz 555 2026-03-13 20:15:30
2445 wumrlvwz 1ojeO6uop'; waitfor delay '0:0:15' -- 2026-03-13 20:15:29
2442 wumrlvwz 555 2026-03-13 20:15:28
2441 wumrlvwz 1-1 waitfor delay '0:0:15' -- 2026-03-13 20:15:27
2438 wumrlvwz @@8C2Ub 2026-03-13 20:15:27
2437 wumrlvwz 555????%2527%2522\'\" 2026-03-13 20:15:27
2436 wumrlvwz 555'" 2026-03-13 20:15:26
2435 wumrlvwz 555 2026-03-13 20:15:26
2434 wumrlvwz 555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' 2026-03-13 20:15:26
2433 wumrlvwz 1-1); waitfor delay '0:0:15' -- 2026-03-13 20:15:25
2430 wumrlvwz 555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15) 2026-03-13 20:15:25
2429 wumrlvwz 1-1; waitfor delay '0:0:15' -- 2026-03-13 20:15:24
2426 wumrlvwz 555v7NQ4gA6')) OR 393=(SELECT 393 FROM PG_SLEEP(15))-- 2026-03-13 20:15:23
2425 wumrlvwz (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/ 2026-03-13 20:15:22
2422 wumrlvwz 555iLX2Fo7F') OR 200=(SELECT 200 FROM PG_SLEEP(15))-- 2026-03-13 20:15:21
2421 wumrlvwz 10"XOR(1*if(now()=sysdate(),sleep(15),0))XOR"Z 2026-03-13 20:15:20
2418 wumrlvwz 555UsRAzpE6' OR 499=(SELECT 499 FROM PG_SLEEP(15))-- 2026-03-13 20:15:19
2417 wumrlvwz 10'XOR(1*if(now()=sysdate(),sleep(15),0))XOR'Z 2026-03-13 20:15:18
2414 wumrlvwz 555-1)) OR 10=(SELECT 10 FROM PG_SLEEP(15))-- 2026-03-13 20:15:18
2413 wumrlvwz 1*if(now()=sysdate(),sleep(15),0) 2026-03-13 20:15:16
2406 wumrlvwz 555-1) OR 467=(SELECT 467 FROM PG_SLEEP(15))-- 2026-03-13 20:15:14
2404 wumrlvwz -1" OR 2+895-895-1=0+0+0+1 -- 2026-03-13 20:15:12
2403 wumrlvwz -1' OR 2+823-823-1=0+0+0+1 or 'gvnaXIqa'=' 2026-03-13 20:15:12
2402 wumrlvwz -1' OR 2+740-740-1=0+0+0+1 -- 2026-03-13 20:15:12
2401 wumrlvwz -1 OR 2+503-503-1=0+0+0+1 2026-03-13 20:15:12
2400 wumrlvwz -1 OR 2+650-650-1=0+0+0+1 -- 2026-03-13 20:15:12
2399 wumrlvwz 1 2026-03-13 20:15:12
2397 wumrlvwz 555-1 OR 90=(SELECT 90 FROM PG_SLEEP(15))-- 2026-03-13 20:15:11
2395 wumrlvwz 1 2026-03-13 20:15:10
2393 wumrlvwz 5552rbVs7SB'; waitfor delay '0:0:15' -- 2026-03-13 20:15:10
2386 wumrlvwz 555-1 waitfor delay '0:0:15' -- 2026-03-13 20:15:08
2384 wumrlvwz 555-1); waitfor delay '0:0:15' -- 2026-03-13 20:15:06
2382 wumrlvwz 555-1; waitfor delay '0:0:15' -- 2026-03-13 20:15:04
2376 wumrlvwz (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/ 2026-03-13 20:15:01
2374 wumrlvwz 5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z 2026-03-13 20:15:00
2372 wumrlvwz 5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z 2026-03-13 20:14:58
2370 wumrlvwz 555*if(now()=sysdate(),sleep(15),0) 2026-03-13 20:14:54
2368 wumrlvwz -1" OR 2+606-606-1=0+0+0+1 -- 2026-03-13 20:14:47
2367 wumrlvwz -1' OR 2+174-174-1=0+0+0+1 or 'EKF1eZUz'=' 2026-03-13 20:14:47
2366 wumrlvwz -1' OR 2+588-588-1=0+0+0+1 -- 2026-03-13 20:14:47
2365 wumrlvwz -1 OR 2+476-476-1=0+0+0+1 2026-03-13 20:14:47
2364 wumrlvwz -1 OR 2+438-438-1=0+0+0+1 -- 2026-03-13 20:14:47
2363 wumrlvwz 555 2026-03-13 20:14:41
2361 wumrlvwz 555 2026-03-13 20:14:34
2359 wumrlvwz 555 2026-03-13 20:14:33
2358 wumrlvwz 555 2026-03-13 20:14:28
2357 wumrlvwz 555 2026-03-13 20:14:28
2356 wumrlvwz 555 2026-03-13 20:14:28
2355 wumrlvwz 555 2026-03-13 20:14:28
2353 wumrlvwz 555 2026-03-13 20:14:22
2351 wumrlvwz 555 2026-03-13 20:14:20
2349 wumrlvwz 555 2026-03-13 20:14:17
2347 wumrlvwz 555 2026-03-13 20:14:15
2345 wumrlvwz 555 2026-03-13 20:14:13
2343 wumrlvwz 555 2026-03-13 20:14:06
2337 wumrlvwz 555 2026-03-13 20:13:40
2335 wumrlvwz 555 2026-03-13 20:13:38
2333 wumrlvwz 555 2026-03-13 20:13:36
2324 wumrlvwz 555 2026-03-13 20:13:35
2323 wumrlvwz 555 2026-03-13 20:13:34
2322 wumrlvwz 555 2026-03-13 20:13:34
2321 wumrlvwz 555 2026-03-13 20:13:34
2320 wumrlvwz 555 2026-03-13 20:13:34
2319 wumrlvwz 555 2026-03-13 20:13:34
2318 wumrlvwz 555 2026-03-13 20:13:34
2317 wumrlvwz 555 2026-03-13 20:13:34
2316 wumrlvwz 555 2026-03-13 20:13:34
2314 wumrlvwz 555 2026-03-13 20:13:34
2313 wumrlvwz 555 2026-03-13 20:13:34
2144 ubataecj 555 2024-05-01 03:52:27
2142 ubataecj @@yT0NO 2024-05-01 03:38:41
2141 ubataecj 555????%2527%2522\'\" 2024-05-01 03:38:41
2140 ubataecj 555'" 2024-05-01 03:38:41
2139 ubataecj 555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' 2024-05-01 03:38:41
2135 ubataecj 555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15) 2024-05-01 03:38:37
2133 ubataecj 555v1xDKDb2')) OR 528=(SELECT 528 FROM PG_SLEEP(15))-- 2024-05-01 03:38:34
2131 ubataecj 555t5BAWglH') OR 402=(SELECT 402 FROM PG_SLEEP(15))-- 2024-05-01 03:38:28
2129 ubataecj 5557t8zcvB8' OR 234=(SELECT 234 FROM PG_SLEEP(15))-- 2024-05-01 03:38:25
2127 ubataecj 555-1)) OR 88=(SELECT 88 FROM PG_SLEEP(15))-- 2024-05-01 03:38:21
2125 ubataecj 555-1) OR 510=(SELECT 510 FROM PG_SLEEP(15))-- 2024-05-01 03:38:18
2123 ubataecj 555-1 OR 510=(SELECT 510 FROM PG_SLEEP(15))-- 2024-05-01 03:38:13
2121 ubataecj 555bz5UAASv'; waitfor delay '0:0:15' -- 2024-05-01 03:38:09
2119 ubataecj 555-1 waitfor delay '0:0:15' -- 2024-05-01 03:38:07
2117 ubataecj 555-1); waitfor delay '0:0:15' -- 2024-05-01 03:38:05
2115 ubataecj 555-1; waitfor delay '0:0:15' -- 2024-05-01 03:38:00
2113 ubataecj (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/ 2024-05-01 03:37:57
2109 ubataecj 5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z 2024-05-01 03:37:53
2106 ubataecj 5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z 2024-05-01 03:37:51
2103 ubataecj 555*if(now()=sysdate(),sleep(15),0) 2024-05-01 03:37:49
2100 ubataecj -1" OR 2+540-540-1=0+0+0+1 -- 2024-05-01 03:37:46
2099 ubataecj -1' OR 2+480-480-1=0+0+0+1 or 'b3MLjESj'=' 2024-05-01 03:37:46
2098 ubataecj -1' OR 2+65-65-1=0+0+0+1 -- 2024-05-01 03:37:46
2097 ubataecj -1 OR 2+107-107-1=0+0+0+1 2024-05-01 03:37:46
2096 ubataecj -1 OR 2+606-606-1=0+0+0+1 -- 2024-05-01 03:37:46
2095 ubataecj 555 2024-05-01 03:37:46
2087 ubataecj 555 2024-05-01 03:37:42
2084 ubataecj 555 2024-05-01 03:37:39
2083 ubataecj 555 2024-05-01 03:37:39
2082 ubataecj 555 2024-05-01 03:37:39
2081 ubataecj 555 2024-05-01 03:37:39
2075 ubataecj 555 2024-05-01 03:37:37
2072 ubataecj 555 2024-05-01 03:37:33
2069 ubataecj 555 2024-05-01 03:37:31
2066 ubataecj 555 2024-05-01 03:37:28
2063 ubataecj 555 2024-05-01 03:37:25
2060 ubataecj 555 2024-05-01 03:37:22
2058 ubataecj 555 2024-05-01 03:37:19
2055 ubataecj 555 2024-05-01 03:37:15
2052 ubataecj 555 2024-05-01 03:37:12
2049 ubataecj 555 2024-05-01 03:37:10
2048 ubataecj 555 2024-05-01 03:37:09
2047 ubataecj 555 2024-05-01 03:37:09
2046 ubataecj 555 2024-05-01 03:37:09
2045 ubataecj 555 2024-05-01 03:37:09
2044 ubataecj 555 2024-05-01 03:37:08
2036 ubataecj 555 2024-05-01 03:37:01

add comment

Snippet ID: #1036209
Snippet name: G22TradingStrategy
Eternal ID of this version: #1036209/297
Text MD5: f6e548c2d1154244a8b2ff8caa89849c
Transpilation MD5: bf52ca7256a54ccdadf379ea304c1d5e
Author: stefan
Category: javax / trading
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): Yes
Created/modified: 2026-02-15 14:38:51
Source code size: 37110 bytes / 1184 lines
Pitched / IR pitched: No / No
Views / Downloads: 4660 / 6263
Version history: 296 change(s)
Referenced in: #3330 - G22TradingStrategy
#3367 - G22TradingStrategy
#3375 - G22TradingStrategy
#3386 - G22TradingStrategy
#3418 - G22TradingStrategy
#3427 - G22TradingStrategy
#3431 - G22TradingStrategy
#3440 - G22TradingStrategy
#3444 - G22TradingStrategy
#3445 - G22TradingStrategy
#3447 - G22TradingStrategy
#3450 - G22TradingStrategy
#3452 - G22TradingStrategy
#3453 - G22TradingStrategy
#3458 - G22TradingStrategy
#3462 - G22TradingStrategy
#3466 - G22TradingStrategy
#3470 - G22TradingStrategy
#3474 - G22TradingStrategy
#3478 - G22TradingStrategy
#3486 - G22TradingStrategy
#3490 - G22TradingStrategy
#3498 - G22TradingStrategy
#3502 - G22TradingStrategy
#3503 - G22TradingStrategy
#3505 - G22TradingStrategy
#3507 - G22TradingStrategy
#3508 - G22TradingStrategy
#3519 - G22TradingStrategy
#3523 - G22TradingStrategy
#3527 - G22TradingStrategy
#3531 - G22TradingStrategy
#3561 - G22TradingStrategy
#3573 - G22TradingStrategy
#3577 - G22TradingStrategy
#3581 - G22TradingStrategy
#3585 - G22TradingStrategy
#3586 - G22TradingStrategy
#3588 - G22TradingStrategy
#3590 - G22TradingStrategy
#3597 - G22TradingStrategy
#3600 - G22TradingStrategy
#3604 - G22TradingStrategyLbmWANf0
#3608 - G22TradingStrategy
#3609 - -1 OR 2+726-726-1=0+0+0+1 --
#3611 - -1 OR 2+420-420-1=0+0+0+1
#3614 - -1' OR 2+750-750-1=0+0+0+1 --
#3617 - -1' OR 2+289-289-1=0+0+0+1 or 'zcsdERAh'='
#3620 - -1" OR 2+114-114-1=0+0+0+1 --
#3626 - if(now()=sysdate(),sleep(15),0)
#3630 - G22TradingStrategy0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z
#3634 - G22TradingStrategy0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z
#3637 - (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/
#3641 - G22TradingStrategy-1 waitfor delay '0:0:15' --
#3644 - G22TradingStrategyH3tga765'; waitfor delay '0:0:15' --
#3648 - G22TradingStrategy7tP2f3QR' OR 327=(SELECT 327 FROM PG_SLEEP(15))--
#3651 - G22TradingStrategydt91DqLf') OR 411=(SELECT 411 FROM PG_SLEEP(15))--
#3654 - G22TradingStrategyMEd5y4X9')) OR 683=(SELECT 683 FROM PG_SLEEP(15))--
#3658 - G22TradingStrategy'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'
#3660 - G22TradingStrategy
#3661 - G22TradingStrategy'"
#3663 - G22TradingStrategy
#3665 - @@f94EC
#3667 - G22TradingStrategy
#3670 - G22TradingStrategy
#3677 - G22TradingStrategy
#3680 - G22TradingStrategy
#3685 - G22TradingStrategy
#3688 - G22TradingStrategy
#3692 - G22TradingStrategy
#3700 - G22TradingStrategy
#3703 - G22TradingStrategy
#3706 - G22TradingStrategy
#3709 - G22TradingStrategy
#3712 - G22TradingStrategy
#3715 - G22TradingStrategy
#3718 - G22TradingStrategy
#3721 - G22TradingStrategy
#3724 - G22TradingStrategy
#3734 - G22TradingStrategy
#3738 - G22TradingStrategy
#3746 - G22TradingStrategy
#3747 - G22TradingStrategy
#3748 - G22TradingStrategy
#3749 - G22TradingStrategy
#3751 - G22TradingStrategy
#3759 - G22TradingStrategy
#3767 - G22TradingStrategy
#3773 - G22TradingStrategy
#3800 - G22TradingStrategy
#3804 - G22TradingStrategy
#3808 - G22TradingStrategy
#3816 - G22TradingStrategy
#3823 - G22TradingStrategy
#3826 - G22TradingStrategy
#3828 - G22TradingStrategy
#3830 - G22TradingStrategy
#3833 - G22TradingStrategy
#3834 - G22TradingStrategy
#3838 - G22TradingStrategy
#3842 - G22TradingStrategy
#3851 - G22TradingStrategy
#3859 - G22TradingStrategy
#3864 - G22TradingStrategy
#3868 - G22TradingStrategy
#3873 - G22TradingStrategy
#3878 - G22TradingStrategy
#3883 - G22TradingStrategy
#3897 - G22TradingStrategy
#3898 - G22TradingStrategy
#3899 - G22TradingStrategy
#3900 - G22TradingStrategy
#3902 - G22TradingStrategy
#3907 - G22TradingStrategy
#3912 - G22TradingStrategy
#3917 - G22TradingStrategy
#3927 - G22TradingStrategy
#3928 - G22TradingStrategy
#3930 - G22TradingStrategy
#3931 - G22TradingStrategy
#3932 - G22TradingStrategy
#3933 - G22TradingStrategy
#3938 - G22TradingStrategy
#3943 - G22TradingStrategy
#3948 - G22TradingStrategy
#3957 - G22TradingStrategy
#3962 - G22TradingStrategy
#3970 - G22TradingStrategy
#3975 - G22TradingStrategy
#3980 - G22TradingStrategy
#3989 - G22TradingStrategy
#3999 - G22TradingStrategy
#4008 - G22TradingStrategy
#4013 - G22TradingStrategy
#4018 - G22TradingStrategy
#4023 - G22TradingStrategy
#4031 - G22TradingStrategy
#4041 - G22TradingStrategy
#4042 - G22TradingStrategy
#4044 - G22TradingStrategy
#4045 - G22TradingStrategy
#4046 - G22TradingStrategy
#4051 - G22TradingStrategy
#4056 - G22TradingStrategy
#4061 - G22TradingStrategy
#4068 - G22TradingStrategy
#4071 - G22TradingStrategy
#4072 - G22TradingStrategy
#4075 - G22TradingStrategy
#4076 - G22TradingStrategy
#4077 - G22TradingStrategy
#4082 - G22TradingStrategy
#4087 - G22TradingStrategy
#4092 - G22TradingStrategy
#4101 - G22TradingStrategy
#4105 - G22TradingStrategy
#4113 - G22TradingStrategy
#4116 - G22TradingStrategy
#4119 - G22TradingStrategy
#4122 - G22TradingStrategy
#4125 - G22TradingStrategy
#4132 - G22TradingStrategy
#4135 - G22TradingStrategy
#4138 - G22TradingStrategy
#4141 - G22TradingStrategy
#4149 - G22TradingStrategy
#4156 - G22TradingStrategy
#4157 - G22TradingStrategy
#4158 - G22TradingStrategy
#4159 - G22TradingStrategy
#4160 - G22TradingStrategy
#4162 - G22TradingStrategy
#4164 - G22TradingStrategy
#4166 - G22TradingStrategy
#4168 - G22TradingStrategy
#4169 - G22TradingStrategy
#4170 - G22TradingStrategy
#4171 - G22TradingStrategy
#4172 - G22TradingStrategy
#4173 - G22TradingStrategy
#4175 - G22TradingStrategy
#4177 - G22TradingStrategy
#4179 - G22TradingStrategy
#4181 - G22TradingStrategy
#4187 - G22TradingStrategy
#4189 - G22TradingStrategy
#4191 - G22TradingStrategy
#4193 - G22TradingStrategy
#4195 - G22TradingStrategy
#4197 - G22TradingStrategy
#4199 - G22TradingStrategy
#4201 - G22TradingStrategy
#4203 - G22TradingStrategy
#4205 - G22TradingStrategy
#4207 - G22TradingStrategy
#4209 - G22TradingStrategy
#4210 - G22TradingStrategy
#4211 - G22TradingStrategy
#4212 - G22TradingStrategy
#4213 - G22TradingStrategy
#4341 - G22TradingStrategy
#1003674 - Standard Classes + Interfaces (LIVE continued in #1034167)
#1036211 - TradingSignal (old)
#1036231 - TradingStrategy (old)
#1036258 - G22TradingStrategy backup
#1039111 - G22TradingStrategy
#1039119 - G22TradingStrategy
#1039120 - G22TradingStrategy
#1039121 - G22TradingStrategy
#1039123 - G22TradingStrategy
#1039125 - G22TradingStrategy
#1039129 - G22TradingStrategy
#1039137 - G22TradingStrategy
#1039141 - G22TradingStrategy
#1039145 - G22TradingStrategy
#1039149 - G22TradingStrategy
#1039155 - G22TradingStrategy
#1039158 - G22TradingStrategy
#1039161 - G22TradingStrategy
#1039164 - G22TradingStrategy
#1039170 - G22TradingStrategy
#1039171 - G22TradingStrategy
#1039172 - G22TradingStrategy
#1039173 - G22TradingStrategy