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).

1  
abstract concept G22TradingStrategy extends ConceptWithChangeListeners is Comparable<G22TradingStrategy>, Juiceable {
2  
  S fieldsToReset aka fieldsToReset_G22TradingStrategy() {
3  
    ret [[
4  
      globalID active
5  
      q
6  
      archived primed usingLiveData 
7  
      backDataFed startTime deactivated closedItself
8  
      log timedLog currentTime currentPrice feedNote
9  
      direction
10  
      digitizer maxDebt direction oldPrice startingPrice
11  
      strategyCrest
12  
      maxInvestment maxDrawdown
13  
      realizedProfit realizedCoinProfit
14  
      realizedWins realizedCoinWins
15  
      realizedLosses realizedCoinLosses
16  
      stepCount stepSince
17  
      openPositions closedPositions positionsThatFailedToOpen
18  
      drift driftSystem
19  
    ]];
20  
  }
21  
  
22  
  settable bool verbose;
23  
  
24  
  gettable S globalID = aGlobalID();
25  
  
26  
  // user-given name, overriding the technical name
27  
  settable S customName;
28  
  
29  
  // user-given comment
30  
  settable S comment;
31  
32  
  gettable transient Q q = startQ();
33  
  
34  
  // link to market (optional)
35  
  transient settable IFuturesMarket market;
36  
  
37  
  settable bool mergePositionsForMarket;
38  
  
39  
  settableWithVar S cryptoCoin;
40  
  settableWithVar S marginCoin = "USDT";
41  
  
42  
  // Which exchange are we using ("Bitget", "ByBit" etc.)
43  
  settableWithVar S exchangeName;
44  
  
45  
  new Ref<G22TradingAccount> tradingAccount;
46  
  
47  
  // Optional: Exchange we get our price data from, if different from above
48  
  settableWithVar S priceDataFromExchange;
49  
  
50  
  // An identifier of the trading account (as of yet unused)
51  
  settableWithVar S accountName;
52  
  
53  
  // primed = started but waiting for first price
54  
  settableWithVar bool primed;
55  
  
56  
  settableWithVar bool usingLiveData;
57  
  settableWithVar bool doingRealTrades;
58  
  settableWithVar bool demoCoin;
59  
  settableWithVar bool active;
60  
  
61  
  // set to date when strategy ended itself
62  
  settableWithVar long closedItself;
63  
  
64  
  // set to date when strategy was deactivated (by itself or by the user)
65  
  settableWithVar long deactivated;
66  
  
67  
  // moved to archive (out of main list)
68  
  settableWithVar bool archived;
69  
  
70  
  // area where this strategy is held, e.g. "Candidates"
71  
  settableWithVar S area;
72  
  
73  
  settableWithVar double adversity = 0.2;
74  
  
75  
  // should migrate to the timedLog completely
76  
  settableWithVar new LS log;
77  
  
78  
  // O is always a string for now
79  
  settableWithVar new L<WithTimestamp<O>> timedLog;
80  
  
81  
  settableWithVar double epsilon = 1e-6;
82  
  
83  
  // increment of crypto we can bet on
84  
  settableWithVar double cryptoStep = 0.0001;
85  
  
86  
  // minimum crypto we need to bet on
87  
  settableWithVar double minCrypto = 0.0001;
88  
  
89  
  // maximum crypto we can bet on
90  
  settableWithVar double maxCrypto = infinity();
91  
  
92  
  settableWithVar double maxInvestment;
93  
  
94  
  // highest value of coinProfit
95  
  settableWithVar double strategyCrest;
96  
  
97  
  // Maximum drawdown seen on account (realized+unrealized)
98  
  settableWithVar double maxDrawdown;
99  
  
100  
  settableWithVar double cellSize = 1;
101  
  
102  
  // position options
103  
  settableWithVar double leverage = 1;
104  
  settableWithVar double marginPerPosition = 1; // in USDT
105  
  
106  
  // optional (for compounding): how much of the account's equity to risk per position
107  
  settableWithVar double riskPerTrade; // in percent
108  
  
109  
  // Equity risked in last trade
110  
  settableWithVar double riskedEquity;
111  
  
112  
  settableWithVar bool showClosedPositionsBackwards = true;
113  
  
114  
  // End strategy when this margin coin profit is reached.
115  
  settableWithVar double takeCoinProfit = infinity();
116  
  settableWithVar bool takeCoinProfitEnabled;
117  
  
118  
  // How many hours of recent back data this algorithm likes
119  
  // to be fed with prior to running live.
120  
  settableWithVar double backDataHoursWanted;
121  
  
122  
  // Did we feed the back data?
123  
  settableWithVar bool backDataFed;
124  
  
125  
  // Juicer that is used to stop the whole strategy depending
126  
  // on its profit (optional)
127  
  settableWithVar AbstractJuicer strategyJuicer;
128  
  
129  
  swappable long currentTime() { ret now(); }
130  
  
131  
  settable transient bool logToPrint = true;
132  
  
133  
  // Note from price feeder
134  
  settableWithVar S feedNote;
135  
  
136  
  // optimization to save fees
137  
  settableWithVar bool useDriftSystem;
138  
  
139  
  // The drift system we are connected to
140  
  settableWithVar G22DriftSystem driftSystem;
141  
  
142  
  // Set to the actual ticker used by the system
143  
  settableWithVar transient TickerSequence actualTicker;
144  
  
145  
  // How many minutes to wait after closing a position
146  
  // before a new one can be opened (0 for no cooldown)
147  
  settableWithVar double cooldownMinutes;
148  
  
149  
  // An image showing this strategy's current state
150  
  settable transient BufferedImage image;
151  
  settable transient byte[] imageForWebServer;
152  
  
153  
  // Initial assumed equity for backtest.
154  
  // If not zero, marginPerPosition will be scaled up and down
155  
  // relative to compoundingBaseEquity+realizedCoinProfit()
156  
  settableWithVar double compoundingBaseEquity;
157  
  
158  
  // Use the exchange's TP & SL features
159  
  settableWithVar bool tpSlOnPlatform;
160  
  
161  
  // Use a limit order for TP instead of market order
162  
  settableWithVar bool useLimitTP;
163  
  
164  
  // Strategies are listed according to this key field (alphanum-IC)
165  
  settableWithVar S listOrder;
166  
  
167  
  // add fields here
168  
  
169  
  <A> A log(A o) {
170  
    if (o != null) {
171  
      S s = str(o);
172  
      long time = currentTime();
173  
      log.add(printIf(logToPrint, "[" + formatLocalDateWithSeconds(time) + "] " + s));
174  
      timedLog.add(withTimestamp(time, s));
175  
      change();
176  
    }
177  
    ret o;
178  
  }
179  
  
180  
  void logVars(O... o) {
181  
    log(renderVars(o));
182  
  }
183  
  
184  
  LS activationStatus() {
185  
    ret llNempties(
186  
      active ? "Active" : "Inactive",
187  
      exchangeName,
188  
      empty(cryptoCoin) ? null
189  
        : "coin: " + cryptoCoin + " over " + marginCoin
190  
          + stringIf(demoCoin, " (demo coin)"),
191  
      stringIf(market != null, "connected to market"),
192  
      stringIf(usingLiveData, "using live data"),
193  
      stringIf(doingRealTrades, "real trades")
194  
    );
195  
  }
196  
  
197  
  double unrealizedProfit() {
198  
    double sum = 0;
199  
    for (p : openPositions())
200  
      sum += p.profit();
201  
    ret sum;
202  
  }
203  
  
204  
  double openMargins() {
205  
    double sum = 0;
206  
    for (p : openPositions())
207  
      sum += p.margin();
208  
    ret sum;
209  
  }
210  
  
211  
  double unrealizedCoinProfit() {
212  
    ret unrealizedCoinProfitAtPrice(currentPrice);
213  
  }
214  
  
215  
  double unrealizedCoinProfitAtPrice(double price) {
216  
    double sum = 0;
217  
    for (p : openPositions)
218  
      sum += p.coinProfitAtPrice(price);
219  
    ret sum;
220  
  }
221  
  
222  
  L<Position> positionsInDirection(int direction) {
223  
    ret filter(openPositions, p -> sign(p.direction) == sign(direction));
224  
  }
225  
  
226  
  L<Position> longPositions() { ret positionsInDirection(1); }
227  
  L<Position> shortPositions() { ret positionsInDirection(-1); }
228  
  
229  
  L<Position> shortPositionsAtOrBelowPrice(double openingPrice) {
230  
    ret filter(openPositions, p -> p.isShort() && p.openingPrice <= openingPrice);
231  
  }
232  
  
233  
  L<Position> longPositionsAtOrAbovePrice(double openingPrice) {
234  
    ret filter(openPositions, p -> p.isLong() && p.openingPrice >= openingPrice);
235  
  }
236  
  
237  
  L<Position> negativePositions() {
238  
    ret filter(openPositions, p -> p.profit() < 0);
239  
  }
240  
  
241  
  double debt() {
242  
    ret max(0, -unrealizedCoinProfit());
243  
  }
244  
  
245  
  // TODO: remove
246  
  double profit() {
247  
    ret realizedProfit+unrealizedProfit();
248  
  }
249  
  
250  
  double coinProfit() {
251  
    ret realizedCoinProfit+unrealizedCoinProfit();
252  
  }
253  
  
254  
  double coinProfitAtPrice(double price) {
255  
    ret realizedCoinProfit+unrealizedCoinProfitAtPrice(price);
256  
  }
257  
  
258  
  S formatProfit(double x) {
259  
    ret plusMinusFix(formatDouble1(x));
260  
  }
261  
  
262  
  settableWithVar PriceDigitizer2 digitizer;
263  
  
264  
  // TODO: This doesn't belong here
265  
  settableWithVar int direction;
266  
  
267  
  // maximum debt seen
268  
  settableWithVar double maxDebt;
269  
  //settableWithVar double minCoinProfit;
270  
  //settableWithVar double maxBoundCoin;
271  
272  
  class Position {
273  
    gettable S positionID = aGlobalID();
274  
275  
    settable double marginToUse;
276  
    settable double openingPrice;
277  
    settable double direction;
278  
    settable double digitizedOpeningPrice;
279  
    gettable double closingPrice = Double.NaN;
280  
    long openingStep, closingStep;
281  
    gettable long openingTime;
282  
    gettable long closingTime;
283  
    double leverage;
284  
    settable double cryptoAmount;
285  
    settable O openReason;
286  
    settable O openError;
287  
    settable O closeReason;
288  
    settable O closeError;
289  
    gettable double margin;
290  
    settable bool openedOnMarket;
291  
    settable S openOrderID; // open order ID returned from platform
292  
    settable S tpOrderID; // tp limit order ID returned from platform
293  
    settable bool closedOnMarket;
294  
    settable bool dontCloseOnMarket;
295  
    settable S comment;
296  
    settable L<AbstractJuicer> juicers;
297  
    
298  
    settable Double tpPrice;
299  
    settable Double slPrice;
300  
    
301  
    // highest and lowest unrealized P&L seen (after leverage)
302  
    settable double crest = negativeInfinity();
303  
    settable double antiCrest = infinity();
304  
305  
    G22TradingStrategy strategy() { ret G22TradingStrategy.this; }
306  
    
307  
    {
308  
      if (!dynamicObjectIsLoading()) {
309  
        marginToUse = marginToUseForNewPosition();
310  
        openingStep = stepCount;
311  
        leverage = G22TradingStrategy.this.leverage;
312  
      }
313  
    }
314  
    
315  
    bool isLong() { ret direction > 0; }
316  
    bool isShort() { ret direction < 0; }
317  
    
318  
    bool closed() { ret !isNaN(closingPrice); }
319  
    S type() { ret trading_directionToPositionType(direction); }
320  
    
321  
    long closingOrCurrentTime() { ret closed() ? closingTime() : currentTime(); }
322  
    
323  
    long duration() { ret closingOrCurrentTime()-openingTime(); }
324  
    
325  
    double profitAtPrice(double price) {
326  
      ret profitAtPriceBeforeLeverage(price)*leverage;
327  
    }
328  
    
329  
    double profitAtPriceBeforeLeverage(double price) {
330  
      ret ((price-openingPrice)/openingPrice*direction*100-adversity);
331  
    }
332  
    
333  
    double workingPrice() {
334  
      ret closed() ? closingPrice : currentPrice();
335  
    }
336  
    
337  
    double profit() {
338  
      ret profitAtPrice(workingPrice());
339  
    }
340  
    
341  
    double profitBeforeLeverage() {
342  
      ret profitAtPriceBeforeLeverage(workingPrice());
343  
    }
344  
    
345  
    settable Double imaginaryProfit;
346  
    
347  
    double coinProfit() {
348  
      try object imaginaryProfit;
349  
      ret coinProfitAtPrice(workingPrice());
350  
    }
351  
    
352  
    bool isOpenError() { ret openError != null; }
353  
    
354  
    double coinProfitAtPrice(double price) {
355  
      ret isOpenError() ? 0 : profitAtPrice(price)/100*margin();
356  
    }
357  
    
358  
    void close(O closeReason) {
359  
      if (closed()) fail("Can't close again");
360  
      if (closeReason != null) closeReason(closeReason);
361  
      closingPrice = currentPrice();
362  
      closingTime = currentTime();
363  
      closingStep = stepCount;
364  
      closeOnMarket();
365  
      
366  
      // This only executes when the market close succeeds
367  
      postClose();
368  
    }
369  
    
370  
    void postClose() {
371  
      openPositions.remove(this);
372  
      if (!isOpenError()) 
373  
        closedPositions.add(this);
374  
      addToRealizedStats();
375  
      log(this);
376  
      //print(this);
377  
      //printPositions();
378  
    }
379  
    
380  
    Position partialClose(double amount, O closeReason) {
381  
      new Position p;
382  
      p.cryptoAmount = cryptoAmount-amount;
383  
      log("Partial close (" + amount + ") of " + this + ", creating remainder position with amount " + p.cryptoAmount + ". Reason: " + closeReason);
384  
      cryptoAmount = amount;
385  
      ret openPosition(p, (int) direction, closeReason);
386  
    }
387  
    
388  
    void makeFake(double coinProfit) {
389  
      closeReason("Fake");
390  
      imaginaryProfit(coinProfit);
391  
      closedPositions.add(this);
392  
      addToRealizedStats();
393  
      log(this);
394  
    }
395  
    
396  
    void addToRealizedStats {
397  
      double cp = coinProfit();
398  
      realizedProfit += profit();
399  
      realizedCoinProfit += cp;
400  
      if (cp > 0) {
401  
        realizedWins++;
402  
        realizedCoinWins += cp;
403  
      } else {
404  
        realizedLosses++;
405  
        realizedCoinLosses += cp;
406  
      }
407  
      change();
408  
    }
409  
    
410  
    S winnerOrLoser() {
411  
      var profit = coinProfit();
412  
      if (profit == 0) ret "NEUTRAL";
413  
      if (profit > 0) ret "WIN";
414  
      ret "LOSS";
415  
    }
416  
    
417  
    // Position.toString
418  
    toString {
419  
      ret commaCombine(
420  
        spaceCombine(
421  
          !closed() ? null :
422  
            winnerOrLoser()
423  
              + appendBracketed(strOrNull(closeReason))
424  
              + appendBracketed(comment)
425  
              + " " + formatLocalDateWithSeconds(closingTime())
426  
              + " " + formatProfit(profit()) + "% (" + marginCoin + " " + formatMarginProfit(coinProfit()) + ")"
427  
              + " (min " + formatProfit(antiCrest())
428  
              + ", max " + formatProfit(crest()) + ")"
429  
              + ", " + formatDouble1(leverage) + "X " + upper(type())
430  
              + " held " + formatHoursMinutesColonSeconds(duration()),
431  
          
432  
        ),
433  
        openingTime() == 0 ? null : "opened " + formatLocalDateWithSeconds(openingTime())
434  
          + (openReason == null ? "" : " " + roundBracket(str(openReason))),
435  
        "before leverage: " + formatProfit(profitBeforeLeverage()) + "%",
436  
        "margin: " + marginCoin + " " + formatMarginPrice(margin()),
437  
        "crypto: " + formatPrice(cryptoAmount),
438  
        "opening price: " + formatPriceX(openingPrice)
439  
           + (isNaN(digitizedOpeningPrice()) ? "" : " (digitized: " + formatPrice(digitizedOpeningPrice())
440  
           + ")") + (openingStep == 0 ? "" : " @ step " + openingStep),
441  
        !closed() ? null : "closing price: " + formatPriceX(closingPrice)
442  
          + (closingStep == 0 ? "" : " @ step " + closingStep),
443  
        );
444  
    }
445  
    
446  
    bool shouldCloseOnMarket() {
447  
      ret !dontCloseOnMarket && !closedOnMarket;
448  
    }
449  
    
450  
    void closeOnMarket {
451  
      if (!shouldCloseOnMarket()) ret;
452  
      if (isOpenError()) ret with log("Not closing because open error: " + this);
453  
      try {
454  
        if (market != null) {
455  
          if (tpOrderID != null) try {
456  
            log("Cancelling TP order: " + this);
457  
            market.cancelOrder(tpOrderID);
458  
          } catch e {
459  
            log(getStackTrace(e));
460  
          }
461  
          
462  
          log("Closing on market: " + this);
463  
          market.closePosition(new IFuturesMarket.CloseOrder()
464  
            .holdSide(HoldSide.fromInt(direction))
465  
            .cryptoAmount(cryptoAmount)
466  
            .leverage(leverage));
467  
          closedOnMarket(true);
468  
          change();
469  
        }
470  
      } on fail e {
471  
        closeError(toPersistableThrowable(e));
472  
      }
473  
    }
474  
    
475  
    void open {
476  
      margin = cryptoAmount*openingPrice/leverage;
477  
      log("Opening: " + this);
478  
      openingTime = currentTime();
479  
      openPositions.add(this);
480  
      change();
481  
    }
482  
    
483  
    void openOnMarket {
484  
      try {
485  
        if (market != null) {
486  
          log("Opening on market: " + this);
487  
          var order = new IFuturesMarket.OpenOrder()
488  
            .clientOrderID(positionID())
489  
            .holdSide(HoldSide.fromInt(direction))
490  
            .cryptoAmount(cryptoAmount)
491  
            .leverage(leverage)
492  
            .isCross(true);
493  
            
494  
          if (tpSlOnPlatform) {
495  
            if (tpPrice != null && !useLimitTP)
496  
              order.takeProfitPrice(tpPrice);
497  
            if (slPrice != null)
498  
              order.stopLossPrice(slPrice);
499  
          }
500  
          
501  
          market.openPosition(order);
502  
          openOrderID(order.orderID());
503  
          openedOnMarket(true);
504  
          
505  
          if (tpSlOnPlatform && tpPrice != null && useLimitTP) {
506  
            log("Creating limit TP on market: " + this);
507  
            var closeOrder = new IFuturesMarket.CloseOrder()
508  
              .clientOrderID(positionID() + "_Close")
509  
                .holdSide(HoldSide.fromInt(direction))
510  
                .cryptoAmount(cryptoAmount)
511  
                .limitPrice(tpPrice);
512  
              market.closePosition(closeOrder);
513  
              tpOrderID(closeOrder.orderID());
514  
          }
515  
          
516  
          change();
517  
        }
518  
      } catch e {
519  
        openError(toPersistableThrowable(e));
520  
        log("Open error: " + getStackTrace(e));
521  
        positionsThatFailedToOpen.add(this);
522  
        close("Open error");
523  
      }
524  
    }
525  
    
526  
    void updateStats {
527  
      double profit = profit();
528  
      crest(max(crest, profit));
529  
      antiCrest(min(antiCrest, profit));
530  
    }
531  
    
532  
    void addJuicer(AbstractJuicer juicer) {
533  
      juicers(listCreateAndAdd(juicers, juicer));
534  
    }
535  
    
536  
    void removeJuicer(AbstractJuicer juicer) {
537  
      juicers(removeDyn(juicers, juicer));
538  
    }
539  
    
540  
    // Call this when position was closed manually on the platform
541  
    void notification_closedOutsideOfStrategy() {
542  
      closedOnMarket(true);
543  
      close("Closed outside of strategy");
544  
    }
545  
    
546  
  } // end of Position
547  
      
548  
  gettable double currentPrice = 0;
549  
  
550  
  gettable double oldPrice = Double.NaN;
551  
  gettable double startingPrice = Double.NaN;
552  
  settable long startTime;
553  
  settableWithVar double realizedProfit;
554  
  settableWithVar double realizedCoinProfit;
555  
  settableWithVar int realizedWins;
556  
  settableWithVar double realizedCoinWins;
557  
  settableWithVar int realizedLosses;
558  
  settableWithVar double realizedCoinLosses;
559  
  settableWithVar long stepCount;
560  
  settableWithVar long stepSince;
561  
  new LinkedHashSet<Position> openPositions;
562  
  gettable new L<Position> closedPositions;
563  
  gettable new L<Position> positionsThatFailedToOpen;
564  
  
565  
  void closeOnMarketMerged(Cl<? extends Position> positions) {
566  
    if (market == null) ret;
567  
    var list = filter(positions, -> .shouldCloseOnMarket());
568  
    closeOnMarketMerged_oneDirection(filter(list, -> .isShort()));
569  
    closeOnMarketMerged_oneDirection(filter(list, -> .isLong()));
570  
  }
571  
  
572  
  // all positions must have the same direction
573  
  void closeOnMarketMerged_oneDirection(L<? extends Position> positions) {
574  
    if (empty(positions)) ret;
575  
    
576  
    double direction = first(positions).direction;
577  
    double cryptoAmount = doubleSum(positions, -> .cryptoAmount);
578  
    log("Closing on market: " + positions);
579  
    
580  
    try {
581  
      market.closePosition(new IFuturesMarket.CloseOrder()
582  
        .holdSide(HoldSide.fromInt(direction))
583  
        .cryptoAmount(cryptoAmount);
584  
        
585  
      for (p : positions)
586  
        p.closedOnMarket(true);
587  
      change();
588  
    } catch e {
589  
      var e2 = toPersistableThrowable(e);
590  
      for (p : positions)
591  
        p.closeError(e2);
592  
      throw e;
593  
    }
594  
  }
595  
596  
  bool hasPosition(double price, double direction) {
597  
    ret findPosition(price, direction) != null;
598  
  }
599  
  
600  
  Position closePosition(double price, double direction, O closeReason) {
601  
    var p = findPosition(price, direction);
602  
    p?.close(closeReason);
603  
    ret p;
604  
  }
605  
  
606  
  void closePositions(Cl<? extends Position> positions, O closeReason default null) {
607  
    if (mergePositionsForMarket)
608  
      closeOnMarketMerged(positions);
609  
    forEach(positions, -> .close(closeReason));
610  
  }
611  
  
612  
  Position findPosition(double digitizedPrice, double direction) {
613  
    ret firstThat(openPositions(), p ->
614  
      diffRatio(p.digitizedOpeningPrice(), digitizedPrice) <= epsilon() && sign(p.direction) == sign(direction));
615  
  }
616  
  
617  
  void printPositions {
618  
    print(colonCombine(n2(openPositions, "open position"),
619  
      joinWithComma(openPositions)));
620  
  }
621  
  
622  
  bool started() { ret !isNaN(startingPrice); }
623  
  void prices(double... prices) {
624  
    fOr (price : prices) {
625  
      if (!active()) ret;
626  
      price(price);
627  
    }
628  
  }
629  
  
630  
  swappable PriceCells makePriceCells(double basePrice) {
631  
    ret new GeometricPriceCells(basePrice, cellSize);
632  
  }
633  
  
634  
  double digitizedPrice() { ret digitizer == null ? Double.NaN : digitizer.digitizedPrice(); }
635  
  double lastDigitizedPrice() { ret digitizer == null ? Double.NaN : digitizer.lastDigitizedPrice(); }
636  
  int digitizedCellNumber() { ret digitizer == null ? 0 : digitizer.cellNumber(); }
637  
  
638  
  void handleNewPriceInQ(double price) {
639  
    q.add(-> price(price));
640  
  }
641  
642  
  void nextStep {
643  
    ++stepCount;
644  
    stepSince(currentTime());
645  
  }
646  
  
647  
  void afterStep {
648  
    double coinProfit = coinProfit();
649  
    maxDebt(max(maxDebt, debt()));
650  
    //minCoinProfit = min(minCoinProfit, coinProfit);
651  
    //maxBoundCoin = max(maxBoundCoin, boundCoin());
652  
    maxInvestment(max(maxInvestment, investment()));
653  
    strategyCrest(max(strategyCrest, coinProfit));
654  
    maxDrawdown(max(maxDrawdown, strategyCrest-coinProfit));
655  
    if (takeCoinProfitEnabled() && coinProfit >= takeCoinProfit) {
656  
      log("Taking coin profit.");
657  
      closeMyself();
658  
    }
659  
    
660  
    for (p : openPositions) p.updateStats();
661  
  }
662  
  
663  
  double investment() {
664  
    ret boundCoin()-realizedCoinProfit;
665  
  }
666  
  
667  
  double boundCoin() {
668  
    ret max(openMargins(), max(0, -coinProfit()));
669  
  }
670  
  
671  
  double fromCellNumber(double cellNumber) { ret cells().fromCellNumber(cellNumber); }
672  
  double toCellNumber(double price) { ret cells().toCellNumber(price); }
673  
  
674  
  L<Position> shortPositionsAtOrBelowDigitizedPrice(double openingPrice) {
675  
    ret filter(openPositions, p -> p.isShort() && p.digitizedOpeningPrice() <= openingPrice);
676  
  }
677  
  
678  
  L<Position> shortPositionsAtOrAboveDigitizedPrice(double openingPrice) {
679  
    ret filter(openPositions, p -> p.isShort() && p.digitizedOpeningPrice() >= openingPrice);
680  
  }
681  
  
682  
  L<Position> longPositionsAtOrAboveDigitizedPrice(double openingPrice) {
683  
    ret filter(openPositions, p -> p.isLong() && p.digitizedOpeningPrice() >= openingPrice);
684  
  }
685  
  
686  
  L<Position> longPositionsAtOrBelowDigitizedPrice(double openingPrice) {
687  
    ret filter(openPositions, p -> p.isLong() && p.digitizedOpeningPrice() <= openingPrice);
688  
  }
689  
  
690  
  PriceCells cells aka priceCells() {
691  
    ret digitizer?.cells;
692  
  }
693  
  
694  
  S formatPriceX(double price) {
695  
    if (isNaN(price)) ret "-";
696  
    S s = formatPrice(price);
697  
    if (cells() == null) ret s;
698  
    double num = cells().priceToCellNumber(price);
699  
    ret s + " (C" + formatDouble2(num) + ")";
700  
  }
701  
  
702  
  abstract void price aka currentPrice(double price);
703  
704  
  bool inCooldown() {  
705  
    if (cooldownMinutes <= 0) false;
706  
    if (nempty(openPositions)) true;
707  
    var lastClosed = last(closedPositions);
708  
    if (lastClosed == null) false;
709  
    var minutes = toMinutes(currentTime()-lastClosed.closingTime);
710  
    ret minutes < cooldownMinutes;
711  
  }
712  
  
713  
  void assureCanOpen(Position p) {
714  
    if (cooldownMinutes > 0) {
715  
      if (nempty(openPositions))
716  
        fail("Already have an open position");
717  
      var lastClosed = last(closedPositions);
718  
      if (lastClosed != null) {
719  
        var minutes = toMinutes(currentTime()-lastClosed.closingTime);
720  
        if (minutes < cooldownMinutes)
721  
          fail("Last position closed " + formatMinutes(fromMinutes(minutes)) + " ago, cooldown is " + cooldownMinutes);
722  
      }
723  
    }
724  
  }
725  
  
726  
  <P extends Position> P openPosition(P p, int direction, O openReason default null) {
727  
    try {
728  
      assureCanOpen(p);
729  
  
730  
      p.openReason(openReason);
731  
      var price = digitizedPrice();
732  
      var realPrice = currentPrice();
733  
      logVars("openPosition", +realPrice, +price, +digitizer);
734  
      if ((isNaN(price) || price == 0) && digitizer != null) {
735  
        price = digitizer.digitizeIndividually(currentPrice());
736  
        print("digitized individually: " + price);
737  
      }
738  
      p.openingPrice(realPrice);
739  
      p.direction(direction);
740  
      p.digitizedOpeningPrice(price);
741  
      
742  
      // Calculate quantity (cryptoAmount) from margin
743  
      // unless cryptoAmount is already set
744  
      
745  
      if (p.cryptoAmount == 0)
746  
        p.cryptoAmount = p.marginToUse/realPrice*leverage;
747  
        
748  
      // Round cryptoAmount to the allowed increments
749  
      p.cryptoAmount = roundTo(cryptoStep, p.cryptoAmount);
750  
      
751  
      // Clamp to minimum/maximum order
752  
      p.cryptoAmount = clamp(p.cryptoAmount, minCrypto, maxCrypto);
753  
      
754  
      log(renderVars("openPosition", +marginPerPosition, +realPrice, +leverage, cryptoAmount := p.cryptoAmount, +cryptoStep));
755  
      p.open();
756  
      //print("Opening " + p);
757  
      //printPositions();
758  
      p.openOnMarket();
759  
      ret p;
760  
    } on fail e {
761  
      log(e);
762  
    }
763  
  }
764  
  
765  
  LS status() {
766  
    double mulProf = multiplicativeProfit();
767  
    ret llNonNulls(
768  
      empty(comment) ? null : "Comment: " + comment,
769  
      "Profit: " + marginCoin + " " + plusMinusFix(formatMarginPrice(coinProfit())),
770  
      "Realized profit: " + marginCoin + " " + formatMarginProfit(realizedCoinProfit) + " from " + n2(closedPositions, "closed position")
771  
        + " (" + formatMarginProfit(realizedCoinWins) + " from " + n2(realizedWins, "win")
772  
        + ", " + formatMarginProfit(realizedCoinLosses) + " from " + n2(realizedLosses, "loss", "losses") + ")",
773  
      "Unrealized profit: " + marginCoin + " " + formatMarginProfit(unrealizedCoinProfit()) + " in " + n2(openPositions, "open position"),
774  
      isNaN(mulProf) ? null : "Multiplicative profit: " + formatProfit(mulProf) + "%",
775  
      //baseToString(),
776  
      !primed() ? null : "Primed",
777  
      !started() ? null : "Started. current price: " + formatPriceX(currentPrice)
778  
        + (isNaN(digitizedPrice()) ? "" : ", digitized: " + formatPriceX(digitizedPrice())),
779  
      (riskPerTrade == 0 ? "" : "Risk per trade: " + formatDouble1(riskPerTrade) + "%. ")
780  
      + "Position size: " + marginCoin + " " + formatPrice(marginPerPosition) + "x" + formatDouble1(leverage) + " = " + marginCoin + " " + formatPrice(positionSize()),
781  
      !usingCells() ? null : "Cell size: " + formatCellSize(cellSize),
782  
      spaceCombine("Step " + n2(stepCount), renderStepSince()),
783  
      //"Debt: " + marginCoin + " " + formatMarginProfit(debt()) + " (max seen: " + formatMarginProfit(maxDebt) + ")",
784  
      "Investment used: " + marginCoin + " " + formatMarginPrice(maxInvestment()),
785  
      strategyJuicer == null ?: "Strategy juicer: " + strategyJuicer,
786  
      //"Drift: " + cryptoCoin + " " + plusMinusFix(formatCryptoAmount(drift())),
787  
    );
788  
  }
789  
  
790  
  S renderStepSince() {
791  
    if (stepSince == 0) ret "";
792  
    ret "since " + (active()
793  
      ? formatHoursMinutesColonSeconds(currentTime()-stepSince)
794  
      : formatLocalDateWithSeconds(stepSince));
795  
  }
796  
  
797  
  LS fullStatus() {
798  
    ret listCombine(
799  
      tradingAccount,
800  
      status(),
801  
      "",
802  
      n2(openPositions, "open position") + ":",
803  
      reversed(openPositions),
804  
      "",
805  
      n2(closedPositions, "closed position")
806  
        + " (" + (showClosedPositionsBackwards ? "latest first" : "oldest first") + "):",
807  
      showClosedPositionsBackwards ? reversed(closedPositions) : closedPositions,
808  
    );
809  
  }
810  
  
811  
  void feed(PricePoint pricePoint) {
812  
    if (!active()) ret;
813  
    setTime(pricePoint.timestamp);
814  
    price(pricePoint.price);
815  
  }
816  
  
817  
  void feed(TickerSequence ts) {
818  
    if (!active()) ret;
819  
    if (ts == null) ret;
820  
    for (pricePoint : ts.pricePoints())
821  
      feed(pricePoint);
822  
  }
823  
  
824  
  public int compareTo(G22TradingStrategy s) {
825  
    ret s == null ? 1 : cmp(coinProfit(), s.coinProfit());
826  
  }
827  
  
828  
  // Returns closed positions
829  
  L<Position> closeAllPositions(O reason default "User close") {
830  
    var positions = openPositions();
831  
    closePositions(positions, reason);
832  
    ret (L) positions;
833  
  }
834  
  
835  
  void closeMyself() {
836  
    closedItself(currentTime());
837  
    closeAllPositionsAndDeactivate();
838  
  }
839  
  
840  
  void closeAllPositionsAndDeactivate {
841  
    deactivate();
842  
    closeAllPositions();
843  
  }
844  
  
845  
  void deactivate {
846  
    market(null);
847  
    if (!active) ret;
848  
    active(false);
849  
    deactivated(currentTime());
850  
    log("Strategy deactivated.");
851  
  }
852  
  
853  
  void reset aka reset_G22TradingStrategy() {
854  
    resetFields(this, fieldsToReset());
855  
    change();
856  
  }
857  
  
858  
  selfType emptyClone aka emptyClone_G22TradingStrategy() {
859  
    var clone = shallowCloneToUnlistedConcept(this);
860  
    clone.reset();
861  
    ret clone;
862  
  }
863  
  
864  
  L<Position> allPositions() {
865  
    ret concatLists(openPositions, closedPositions);
866  
  }
867  
  
868  
  L<Position> sortedPositions() {
869  
    var allPositions = allPositions();
870  
    ret sortedByCalculatedField(allPositions, -> .openingTime());
871  
  }
872  
  
873  
  bool positionsAreNonOverlapping() {
874  
    for (a, b : unpair overlappingPairs(sortedPositions()))
875  
      if (b.openingTime() < a.closingTime())
876  
        false;
877  
    true;
878  
  }
879  
  
880  
  // Profit when applying all positions (somewhat theoretical because you
881  
  // might go below platform limits)
882  
  // Also only works when positions are linear
883  
  double multiplicativeProfit() {
884  
    if (!positionsAreNonOverlapping()) ret Double.NaN;
885  
    double profit = 1;
886  
    for (p : sortedPositions())
887  
      profit *= 1+p.profit()/100;
888  
    ret (profit-1)*100;
889  
  }
890  
  
891  
  bool haveBackData() { ret backDataHoursWanted == 0 | backDataFed; }
892  
  
893  
  bool didRealTrades() {
894  
    ret any(allPositions(), p -> p.openedOnMarket() || p.closedOnMarket());
895  
  }
896  
  
897  
  S formatCellSize(double cellSize) {
898  
    ret formatPercentage(cellSize, 3);
899  
  }
900  
  
901  
  S areaDesc() {
902  
    if (eq(area, "Candidates")) ret "Candidate";
903  
    ret nempty(area) ? area : archived ? "Archived" : "";
904  
  }
905  
  
906  
  selfType setTime aka currentTime(long time) {
907  
    int age = ifloor(ageInHours());
908  
    long lastMod = mod(currentTime()-startTime, hoursToMS(1));
909  
    currentTime = -> time;
910  
    if (ifloor(ageInHours()) > age)
911  
      log("Hourly profit log: " + formatMarginProfit(coinProfit()));
912  
    this;
913  
  }
914  
  
915  
  double ageInHours() { ret startTime == 0 ? 0 : msToHours(currentTime()-startTime); }
916  
  
917  
  // only use near start of strategy, untested otherwise
918  
  selfType changeCellSize(double newCellSize) {
919  
    double oldCellSize = cellSize();
920  
    if (oldCellSize == newCellSize) this;
921  
    cellSize(newCellSize);
922  
    if (digitizer != null)
923  
      digitizer.swapPriceCells(makePriceCells(priceCells().basePrice()));
924  
    log("Changed cell size from " + oldCellSize + " to " + newCellSize);
925  
    this;
926  
  }
927  
  
928  
  bool hasClosedItself() { ret closedItself != 0; }
929  
  
930  
  public double juiceValue() { ret coinProfit(); }
931  
  
932  
  // drift is our cumulative delta (=sum of all signed position
933  
  // quantities)
934  
  double drift() {
935  
    double drift = 0;
936  
    for (p : openPositions())
937  
      drift += p.cryptoAmount()*p.direction();
938  
    ret drift;
939  
  }
940  
  
941  
  S formatCryptoAmount(double amount) {
942  
    ret formatDouble3(amount);
943  
  }
944  
  
945  
  Position openShort() { ret openPosition(-1); }
946  
  Position openLong() { ret openPosition(1); }
947  
  
948  
  Position openPosition(int direction, O openReason default null) {
949  
    new Position p;
950  
    p.marginToUse = marginToUseForNewPosition();
951  
    ret openPosition(p, direction, openReason);
952  
  }
953  
  
954  
  // Open or close positions until the drift (delta) is
955  
  // equal to targetDrift (or as close as the platform's
956  
  // restrictions allow).
957  
  // Returns the list of positions opened or closed
958  
  // (Function is in dev.)
959  
  L<Position> adjustDrift(double targetDrift, O reason default null) {
960  
    new L<Position> changeList;
961  
    
962  
    // target 0? close all
963  
    if (targetDrift == 0)
964  
      ret closeAllPositions(reason);
965  
    
966  
    double drift = drift();
967  
    
968  
    // target already reached? done
969  
    if (drift == targetDrift) ret changeList;
970  
    
971  
    int direction = sign(targetDrift);
972  
    
973  
    // Are we changing direction? Then close everything first.
974  
    if (sign(drift) != direction)
975  
      changeList.addAll(closeAllPositions(reason));
976  
    
977  
    // Now we know targetDrift and drift have the same sign.
978  
    double diff = abs(targetDrift)-abs(drift);
979  
    
980  
    // Round to allow increments
981  
    diff = roundTo(cryptoStep, diff);
982  
    
983  
    if (diff > 0) {
984  
      // We need to open a new position - that's easy
985  
      
986  
      new Position p;
987  
      p.cryptoAmount = diff;
988  
      changeList.add(openPosition(p, direction, reason));
989  
    } else {
990  
      double toClose = -diff;
991  
      
992  
      // We need to close positions - that's a bit more tricky
993  
      
994  
      // Filter by direction to be sure in case there is
995  
      // hedging (you shouldn't do hedging, really, though)
996  
      var positions = filter(openPositions(), p -> p.direction() == direction);
997  
      
998  
      // Let's look for an exact size match first.
999  
      // We rounded to cryptoStep, so using == is ok.
1000  
      var _toClose = toClose;
1001  
      var exactMatch = firstThat(positions, p -> p.cryptoAmount == _toClose);
1002  
      
1003  
      if (exactMatch != null) {
1004  
        exactMatch.close(reason);
1005  
        changeList.add(exactMatch);
1006  
        ret changeList;
1007  
      }
1008  
      
1009  
      // No exact match. Go through positions starting with
1010  
      // the oldest one.
1011  
      
1012  
      for (p : positions) {
1013  
        toClose = roundTo(cryptoStep, toClose);
1014  
        if (toClose == 0) break;
1015  
        if (toClose >= p.cryptoAmount) {
1016  
          // Need to close the whole position
1017  
          toClose -= p.cryptoAmount;
1018  
          p.close(reason);
1019  
          changeList.add(p);
1020  
        } else {
1021  
          // Need a partial close.
1022  
          
1023  
          changeList.add(p);
1024  
          var remainderPosition = p.partialClose(toClose, reason);
1025  
          changeList.add(remainderPosition);
1026  
        }
1027  
      }
1028  
    }
1029  
    
1030  
    ret changeList;
1031  
  }
1032  
  
1033  
  L<Position> winners() { ret filter(closedPositions(), p -> p.coinProfit() > 0); }
1034  
  L<Position> losers() { ret filter(closedPositions(), p -> p.coinProfit() < 0); }
1035  
  
1036  
  L<? extends Position> openPositions() { ret cloneList(openPositions); }
1037  
  
1038  
  double winRate() {
1039  
    ret l(winners()) * 100.0 / l(closedPositions);
1040  
  }
1041  
  
1042  
  bool usingCells() { true; }
1043  
  
1044  
  double positionSize() {
1045  
    ret marginToUseForNewPosition()*leverage;
1046  
  }
1047  
  
1048  
  double marginToUseForNewPosition() {
1049  
    ret scaleMargin(marginPerPosition);
1050  
  }
1051  
  
1052  
  // to simulate compounding in backtest
1053  
  double scaleMargin(double margin) {
1054  
    // Live? Then no scaling.
1055  
    if (usingLiveData) ret margin;
1056  
    
1057  
    ret margin*compoundingFactor();
1058  
  }
1059  
  
1060  
  double compoundingFactor() {
1061  
    // No compounding selected?
1062  
    if (compoundingBaseEquity == 0) ret 1;
1063  
    
1064  
    ret max(0, remainingEquity()/compoundingBaseEquity);
1065  
  }
1066  
  
1067  
  // only for backtesting
1068  
  double remainingEquity() {
1069  
    ret compoundingBaseEquity+realizedCoinProfit();
1070  
  }
1071  
  
1072  
  class RiskToMargin {
1073  
    // in percent
1074  
    settable double riskForTrade = riskPerTrade;
1075  
    
1076  
    settable double stopLossPercent;
1077  
    settable double price = currentPrice();
1078  
    settable double fullEquity;
1079  
    
1080  
    double riskedEquity() {
1081  
      ret fullEquity*riskForTrade/100;
1082  
    }
1083  
    
1084  
    double qty() {
1085  
      ret riskedEquity()/(price*stopLossPercent/100);
1086  
    }
1087  
    
1088  
    double margin aka get() {
1089  
      ret qty()*price/leverage();
1090  
    }
1091  
  }
1092  
  
1093  
  void fixRealizedStats {
1094  
    realizedProfit(0);
1095  
    realizedCoinProfit(0);
1096  
    realizedWins(0);
1097  
    realizedCoinWins(0);
1098  
    realizedLosses(0);
1099  
    realizedCoinLosses(0);
1100  
    for (p : closedPositions()) p.addToRealizedStats();
1101  
  }
1102  
  
1103  
  // p must not be open
1104  
  bool deletePosition(Position p) {
1105  
    if (closedPositions.remove(p) || positionsThatFailedToOpen.remove(p)) {
1106  
      fixRealizedStats();
1107  
      true;
1108  
    }
1109  
    false;
1110  
  }
1111  
  
1112  
  void deletePositionsThatFailedToOpen() {
1113  
    for (p : cloneList(positionsThatFailedToOpen))
1114  
      deletePosition(p);
1115  
  }
1116  
  
1117  
  void deleteAllPositions() {
1118  
    for (p : cloneList(closedPositions))
1119  
      deletePosition(p);
1120  
  }
1121  
  
1122  
  bool hasRiskPerTrade() { ret riskPerTrade != 0; }
1123  
  
1124  
  Position addFakePosition(double coinProfit) {
1125  
    new Position p;
1126  
    p.makeFake(coinProfit);
1127  
    ret p;
1128  
  }
1129  
  
1130  
  // If there is exactly one open position:
1131  
  // Open another position in the same direction
1132  
  // with same size
1133  
  Position pyramid(O openReason default "Pyramiding") {
1134  
    ret extendedPyramid(2, openReason);
1135  
  }
1136  
1137  
  // level: pyramid level to be reached
1138  
  // (must be one higher than current number of positions
1139  
  // to trigger - no double adding at once)
1140  
  Position extendedPyramid(int level, O openReason default "Pyramiding") {
1141  
    if (l(openPositions()) != level-1)
1142  
      null;
1143  
      
1144  
    var p = first(openPositions);
1145  
    new Position p2;
1146  
    p2.cryptoAmount(p.cryptoAmount);
1147  
    ret openPosition(p2, sign(p.direction), openReason);
1148  
  }
1149  
  
1150  
  // level: pyramid level to be reached
1151  
  // can do double adding
1152  
  L<Position> extendedPyramid2(int level, O openReason default "Pyramiding") {
1153  
    new L<Position> newPositions;
1154  
    
1155  
    while (l(openPositions()) < level && l(newPositions) < level) {
1156  
      var p = first(openPositions);
1157  
      new Position p2;
1158  
      p2.cryptoAmount(p.cryptoAmount);
1159  
      newPositions.add(p2);
1160  
      openPosition(p2, sign(p.direction), openReason);
1161  
    }
1162  
    
1163  
    ret newPositions;
1164  
  }
1165  
  
1166  
  Position newPosition() {
1167  
    ret new Position;
1168  
  }
1169  
  
1170  
  void postCloseFix() {
1171  
    for (p : openPositions())
1172  
      if (p.closed()) try {
1173  
        p.postClose();
1174  
      } catch e {
1175  
        log(e);
1176  
      }
1177  
  }
1178  
  
1179  
  void dryCloseAll() {
1180  
    for (p : openPositions())
1181  
      p.dontCloseOnMarket(true);
1182  
    closeAllPositions();
1183  
  }
1184  
}

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: 4659 / 6263
Version history: 296 change(s)
Referenced in: [show references]