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);
double cryptoAmount = p.marginToUse/realPrice*leverage;
cryptoAmount = roundTo(cryptoStep, cryptoAmount);
log(renderVars("openPosition", +marginPerPosition, +realPrice, +leverage, +cryptoAmount, +cryptoStep));
p.cryptoAmount = max(minCrypto, cryptoAmount);
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())),
"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(
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());
}
void closeAllPositions(O reason default "User close") {
closePositions(openPositions(), reason);
}
void closeMyself() {
closedItself(currentTime());
closeAllPositionsAndDeactivate();
}
void closeAllPositionsAndDeactivate {
deactivate();
closeAllPositions();
}
void deactivate {
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