sclass PullbackToProfitAnalysis is Swingable { settable double pullbackLimit = 1.0; settable double adversity = 0.2; settable boolean isShort; settable TickerSequence ticker; settable long startTime; settable L ptpList; settable double openingPrice; double priceToProfit(double price) { var profit = asPercentIncrease(price, openingPrice()); if (isShort()) profit = neg(profit); ret profit.minus(adversity()); } run { if (notNull(ptpList())) ret null; if (startTime().eq(0L)) startTime = ticker().startTime(); var idx1 = ticker().indexOfTimestamp(startTime()); openingPrice(ticker().getPrice(idx1)); var crest = 0.0; //negativeInfinity var maxPullback = 0.0; ptpList = new L; var it = countIterator(idx1, ticker().size()); while (hasNext(it)) { var idx = it.next(); var price = ticker().getPrice(idx); var time = ticker().getTimestamp(idx); var profit = priceToProfit(price); crest = max(crest, profit); var pullback = crest.minus(profit); maxPullback = max(maxPullback, pullback); if (maxPullback >= pullbackLimit()) { printConcat("Ending at pullback ", maxPullback, " (", formatMinutes(time.minus(startTime())), ")"); break; } var result = new PullbackToProfit().startTime(startTime()).pullback(maxPullback).profit(crest.minus(maxPullback)).timestamp(time); if (nempty(ptpList())) { var prev = last(ptpList()); if (prev.replaces(result)) result = null; else if (result.replaces(prev)) popLast(ptpList()); } addIfNotNull(ptpList(), result); } } JComponent visualize() { run(); var endTime = last(ptpList()).timestamp(); var diff = endTime-startTime(); endTime = toLong(startTime()+diff*2); var shortenedTicker = ticker().subSequenceByTimestamps(startTime(), endTime); var painter = new TickerGraphPainter(); fOr (result : ptpList()) { painter.addVerticalLine(result.timestamp()) } var graph = jTickerView shortenedTicker painter; ret jvsplit(graph, jText(lines(ptpList()))); } Object cutOffAfterMinutes(double minutes) { run(); var timestamp = startTime().plus(fromMinutes(minutes)); var ptp = firstThat(ptpList(), p -> p.timestamp().greaterOrEq(timestamp)); if (isNull(ptp)) ret null; var price = ticker().priceAtTimestamp(timestamp); var profit = priceToProfit(price); ret new PullbackToProfit().startTime(startTime()).pullback(ptp.pullback()).profit(profit).timestamp(timestamp); } double maxCleanness() { run(); ret doubleMax(map(ptpList(), ptp -> ptp.cleanness()); } PullbackToProfit cleanestPTP() { run(); ret highestBy(ptpList(), ptp -> ptp.cleanness()); } }