void tl_gotTick(Tick t) { if (archivetickbox.Checked) ta.Save(t); if (!barlist.ContainsKey(t.sym)) barlist.Add(t.sym, new BarList(BarInterval.FiveMin, t.sym)); else barlist[t.sym].newTick(t); if (boxlist.ContainsKey(t.sym) && (boxlist[t.sym] != null)) { Box b = boxlist[t.sym]; BoxInfo bi = new BoxInfo(); Position p = new Position(t.sym); try { p = poslist[t.sym]; } catch (KeyNotFoundException) { } Order o = b.Trade(t, barlist[t.sym], p, bi); o.Security = seclist[t.sym].Type; o.Exchange = seclist[t.sym].DestEx; o.LocalSymbol = seclist[t.sym].Name; tl.SendOrder(o); } }
// these are for calculating closed pl // they do not adjust positions themselves /// <summary> /// Gets the closed PL on a per-share basis, ignoring how many shares are held. /// </summary> /// <param name="existing">The existing position.</param> /// <param name="closing">The portion of the position that's being closed/changed.</param> /// <returns></returns> public static decimal ClosePT(Position existing, Trade adjust) { if (!existing.isValid || !adjust.isValid) throw new Exception("Invalid position provided. (existing:" + existing.ToString() + " adjustment:" + adjust.ToString()); if (existing.Flat) return 0; // nothing to close if (existing.Side == adjust.Side) return 0; // if we're adding, nothing to close return existing.Side ? adjust.Price - existing.Price : existing.Price - adjust.Price; }
protected void Setup() { lp = new Position(stock, entry, lsize); sp = new Position(stock, entry, ssize); //closing trades lc = new Trade(stock, last, lsize / -2); sc = new Trade(stock, last, -ssize); }
// returns any closed PL calculated on position basis (not per share) /// <summary> /// Adjusts the position by applying a new position. /// </summary> /// <param name="pos">The position adjustment to apply.</param> /// <returns></returns> public decimal Adjust(Position pos) { if (this.hasSymbol && (this.Symbol != pos.Symbol)) throw new Exception("Invalid Position: Position MUST have a symbol."); if (!pos.isValid) throw new Exception("Invalid position adjustment, existing:" + this.ToString() + " adjustment:" + pos.ToString()); if (pos.Flat) return 0; // nothing to do decimal pl = BoxMath.ClosePL(this,pos.ToTrade()); if (this.Flat) this.price = pos.price; // if we're leaving flat just copy price else if ((pos.Side && this.Side) || (!pos.Side && !this.Side)) // sides match, adding so adjust price this.price = ((this.price * this.size) + (pos.price * pos.size)) / (pos.size + this.size); this.size += pos.size; // adjust the size if (this.Flat) price = 0; // if we're flat after adjusting, size price back to zero return pl; }
public void UsingTrades() { // long Position p = new Position(new Trade(s, 80, 100,dt)); Assert.That(p.Side); Assert.That(p.Size == 100); decimal pl = p.Adjust(new Trade(s, 84, -100,dt)); Assert.That(p.Flat); Assert.That(pl == (84 - 80) * 100); // short pl = 0; p = new Position(new Trade(s, 84, -100,dt)); Assert.That(!p.Side); Assert.That(p.Size == -100); pl = p.Adjust(new Trade(s, 80, 100,dt)); Assert.That(pl == (84 - 80) * 100); Assert.That(p.Flat); }
public void Basics() { Position p = new Position(s); Assert.That(p.Size == 0); Assert.That(p.hasSymbol); Assert.That(p.AvgPrice == 0); Assert.That(p.Flat); Assert.That(p.isValid); Position p2 = new Position(s, 10, 100); p.Adjust(p2); Assert.That(p.Size == 100); Assert.That(p.hasSymbol); Assert.That(p.AvgPrice == 10); Assert.That(!p.Flat); Assert.That(p.Side); Assert.That(p.isValid); Position p3 = new Position(s, 0, 100); Assert.That(!p3.isValid); p3 = new Position(s, 10, 0); Assert.That(!p3.isValid); p3 = new Position(s, 12, 100); p.Adjust(p3); Assert.That(p.AvgPrice == 11); Assert.That(p.Side); Assert.That(p.isValid); Assert.That(!p.Flat); Assert.That(p.Size == 200); p.Adjust(new Trade(s, 13, -100,dt)); Assert.That(p.AvgPrice == 11); Assert.That(p.Side); Assert.That(p.isValid); Assert.That(!p.Flat); Assert.That(p.Size == 100); Trade lasttrade = new Trade(s, 12, -100,dt); decimal profitFromP2toLASTTRADE = BoxMath.ClosePL(p2, lasttrade); Assert.That(profitFromP2toLASTTRADE == (lasttrade.xprice-p2.AvgPrice)*Math.Abs(lasttrade.xsize)); }
public Position FastPos(string sym) { try { return cpos[sym]; } catch (KeyNotFoundException) { Position p = new Position(sym, AvgPrice(sym), PosSize(sym)); cpos.Add(sym, p); return p; } }
/// <summary> /// Gets the closed points (points = PL on per-share basis) for given symbol/account. /// </summary> /// <param name="symbol">The symbol.</param> /// <param name="account">The account.</param> /// <returns>points</returns> public decimal GetClosedPT(string symbol, Account account) { Position pos = new Position(symbol); decimal points = 0; if (!MasterTrades.ContainsKey(account.ID)) return points; foreach (Trade t in MasterTrades[account.ID]) { points += BoxMath.ClosePT(pos, t); pos.Adjust(t); } return points; }
/// <summary> /// Gets the closed PL for a particular symbol and brokerage account. /// </summary> /// <param name="symbol">The symbol.</param> /// <param name="a">The Account.</param> /// <returns>Closed PL</returns> public decimal GetClosedPL(string symbol, Account a) { Position pos = new Position(symbol); decimal pl = 0; if (!MasterTrades.ContainsKey(a.ID)) return pl; foreach (Trade trade in MasterTrades[a.ID]) { if (trade.symbol == pos.Symbol) pl += pos.Adjust(trade); } return pl; }
/// <summary> /// Gets the open position for the specified account. /// </summary> /// <param name="symbol">The symbol to get a position for.</param> /// <param name="a">the account.</param> /// <returns>current position</returns> public Position GetOpenPosition(string symbol,Account a) { Position pos = new Position(symbol); if (!MasterTrades.ContainsKey(a.ID)) return pos; foreach (Trade trade in MasterTrades[a.ID]) if (trade.symbol==symbol) pos.Adjust(trade); return pos; }
public void MaxSizeTest() { Always b = new Always(); b.MinSize = 100; b.MaxSize = 200; Position p = new Position(s); Order o = new Order(); Assert.That(b.MinSize==100); Assert.That(b.MaxSize==200); for (int i = 0; i < timesales.Length; i++) { Tick t = new Tick(timesales[i]); if (o.isValid && t.isTrade) { o.Fill(t); p.Adjust((Trade)o); o = new Order(); } Assert.That(p.Size<=b.MaxSize); o = b.Trade(timesales[i], new BarList(), p, new BoxInfo()); } Assert.That(p.Size == 200); // Now we'll set maxsize to 100 b = new Always(); b.MinSize = 100; b.MaxSize = 100; p = new Position(s); o = new Order(); Assert.That(b.MinSize == 100); Assert.That(b.MaxSize == 100); for (int i = 0; i < timesales.Length; i++) { Tick t = new Tick(timesales[i]); if (o.isValid && t.isTrade) { o.Fill(t); p.Adjust((Trade)o); o = new Order(); } Assert.That(p.Size <= b.MaxSize); o = b.Trade(timesales[i], new BarList(), p, new BoxInfo()); } Assert.That(p.Size == 100); }
public void ThrottlesTest() { LimitsTest b = new LimitsTest(); // we're skipping the first trade bc it's pre-market and we're not testing // that in this test int i = 1; Order o; Position p = new Position(s); Assert.That(b.Turns == 0); Assert.That(b.Adjusts == 0); Assert.That(b.TradeCaps); Assert.That(!b.Off); Assert.That(b.PosSize == 0); o = b.Trade(timesales[i++], new BarList(), p, new BoxInfo()); Assert.That(o.isValid); // fill our order with next tick and just our position o.Fill(timesales[i]); p.Adjust((Trade)o); Assert.That(b.Adjusts == 1); Assert.That(b.Turns == 0); o = b.Trade(timesales[i++], new BarList(), p, new BoxInfo()); Assert.That(o.isValid); Assert.That(b.Adjusts == 2); Assert.That(b.Turns == 1); // should be flat now o = b.Trade(timesales[i++], new BarList(), new Position(s), new BoxInfo()); Assert.That(!o.isValid); // no more orders, as Assert.That(b.Off); // we should be shutdown }
/// <summary> /// Gets the closed PL on a position basis, the PL that is registered to the account for the entire shares transacted. /// </summary> /// <param name="existing">The existing position.</param> /// <param name="closing">The portion of the position being changed/closed.</param> /// <returns></returns> public static decimal ClosePL(Position existing, Trade adjust) { return ClosePT(existing, adjust) * Math.Abs(adjust.Size); }
public static decimal OpenPL(decimal LastTrade, Position Pos) { return OpenPL(LastTrade, Pos.AvgPrice, Pos.Size); }
/// <summary> /// Trades specified tick. This method will call an inherited overridden member Read if QuickOrder is true or ReadOrder if QuickOrder is false. /// </summary> /// <param name="tick">The tick.</param> /// <param name="bl">The barlist.</param> /// <param name="pos">The current position in the stock or instrument.</param> /// <param name="bi">Other box information.</param> /// <returns></returns> public Order Trade(Tick tick,BarList bl, Position pos,BoxInfo bi) { Order o = new Order(); if (Symbol == null) { if (tick.sym != "") symbol = tick.sym; else throw new Exception("No symbol specified"); _pos = new Position(tick.sym); } if (!pos.isValid) throw new Exception("Invalid Position Provided to Box" + pos.ToString()); if (tick.sym != Symbol) return o; time = tick.time; date = tick.date; sec = tick.sec; if ((Time < DayStart) || (Time>DayEnd)) return o; // is market open? if (Off) return o; // don't trade if shutdown if (TradeCaps && pos.Flat && ((this.turns >= MAXTRADES) || (this.adjusts >= MAXADJUSTS))) { this.Shutdown("Trade limit reached."); return o; } _pos = pos; if (QuickOrder) // user providing only size adjustment { // get our adjustment int adjust = this.Read(tick, bl,bi); // convert adjustment to an order o = this.Adjust(adjust); } else // user providing a complete order, so get it { o = ReadOrder(tick, bl,bi); } if (!OrdersAllowed) // if we're not allowed, mark order as invalid o = new Order(); //flat us at the close if (!_sentshut && (Time >= (DayEnd - DayEndBuff))) { o = this.Adjust(Flat); o.time = Time; o.date = Date; this.Shutdown("end-of-day"); _sentshut = true; } if (o.isValid) { // if it's a valid order it counts as an adjustment adjusts++; // if we're going to flat from non-flat, this is a "trade" if ((Math.Abs(PosSize + o.SignedSize) == 0) && (PosSize != 0)) turns++; // final prep for good orders _expectedpossize += o.SignedSize; o.time = Time; o.date = Date; } if (o.isValid) this.D("Sent order: " + o); return o; // send our order }