Warning: session_start(): open(/var/lib/php/sessions/sess_hiofua06h9ss0812gj1vj19553, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
set flag Reparse.
sclass Corridor {
record noeq Position(/*settable*/ double openingPrice, /*settable*/ double direction) {
/*settable*/ double closingPrice = Double.NaN;
bool closed() { ret !isNaN(closingPrice); }
S type() { ret trading_directionToPositionType(direction); }
double profitAtPrice(double price) {
ret (price-openingPrice)*direction;
}
double profit() {
ret profitAtPrice(closed() ? closingPrice : currentPrice());
}
void close {
if (closed()) fail("Can't close again");
openPositions.remove(this);
closingPrice = currentPrice();
closedPositions.add(this);
realizedProfit += profit();
}
toString {
ret renderFunctionCall(
spaceCombine(
closed() ? "Closed" : null,
type()
),
openingPrice,
"profit=" + profit());
}
}
record noeq Threshold(/*settable*/ double price, /*settable*/ double direction, Runnable action) {
void trigger {
print("Triggered at " + price + " " + direction + ": " + action);
callF(action);
}
}
settable double epsilon = 0.001;
settable double ladderStep = 1;
gettable double currentPrice = 0;
gettable double lastDirection;
gettable double realizedProfit;
new L loops;
new TreeMultiMap thresholds;
new LinkedHashSet openPositions;
new L closedPositions;
record noeq Loop(/*settable*/ double startingPrice, /*settable*/ double direction) {
Position position;
Loop successor;
class Open is Runnable {
run {
if (position != null && !position.closed())
fail("Trying to re-open position: " + this);
print("Opening position at " + currentPrice() + " by loop " + this);
position = openPosition(direction);
if (successor == null)
successor = new Loop(startingPrice+ladderStep, direction).init();
}
toString { ret spaceCombine("Open", startingPrice, direction); }
}
class Close is Runnable {
run {
if (position != null) {
print("Closing position at " + currentPrice() + " by loop " + this);
position.close();
}
}
toString { ret spaceCombine("Close", startingPrice, direction); }
}
selfType init() {
loops.add(this);
addThreshold(startingPrice, -direction, new Open);
addThreshold(startingPrice+ladderStep, direction, new Close);
this;
}
toString {
ret formatRecordVars("Loop",
+startingPrice,
+direction,
+position,
succ := successor == null ?: "t"
);
}
}
Position openPosition(double direction) {
ret addAndReturn(openPositions, new Position(currentPrice(), direction));
}
Threshold addThreshold(double price, double direction, Runnable action) {
var t = new Threshold(price, direction, action);
thresholds.put(t.price, t);
bool triggered = (lastDirection == 0 || lastDirection == direction) && absDiff(currentPrice, price) < epsilon;
printVars addThreshold(+currentPrice, +price, +direction, +lastDirection, +triggered);
if (triggered)
t.trigger();
ret t;
}
void start {
double price = currentPrice();
print("Starting CORRIDOR at " + price + " +/- " + ladderStep);
lastDirection = 0;
new Loop(price, 1).init();
new Loop(price, -1).init();
}
selfType currentPrice aka price(double price) {
double oldPrice = currentPrice;
if (oldPrice == price) this;
currentPrice = price;
int direction = sign(price-oldPrice);
lastDirection = direction;
NavigableMap> map = thresholds.innerMap();
map = direction > 0
? map.subMap(oldPrice, false, price, true)
: map.subMap(price, true, oldPrice, false);
var keys = keys(map);
LL thresholdsCrossed = valuesList(map);
if (direction < 0)
reverseInPlace(thresholdsCrossed);
new L toExecute;
for (actions : thresholdsCrossed)
for (t : actions)
if (t.direction == direction)
toExecute.add(t);
printWithPrecedingNL(commaCombine(
"New price: " + currentPrice,
"direction: " + direction,
"Thresholds crossed: " + keys,
n2(toExecute, "trigger")));
for (t : toExecute) t.trigger();
this;
}
double unrealizedProfit() {
ret doubleSum(map(openPositions, ->.profit()));
}
double profit() {
ret realizedProfit+unrealizedProfit();
}
LS status() {
double up = unrealizedProfit();
ret ll(
"Profit: " + realizedProfit+up,
"Realized profit: " + realizedProfit + " from " + n2(closedPositions, "closed position"),
"Unrealized profit: " + up + " in " + n2(openPositions, "open position"),
//n2(loops, "loop"),
//n2(keysSize(thresholds), "threshold"),
//n2(l(thresholds), "threshold action"),
);
}
toString { ret commaCombine(status()); }
}