public void TradeTesting8() { Performance manager = TradeTickProcessing(0, 0, 30000); TransactionPairBinary expected = TransactionPairBinary.Create(); expected.Enter(1, 105.66, new TimeStamp(2005, 2, 08, 11, 59, 58, 763), emptyTime, 1, 0, 0); expected.Exit(105.75, new TimeStamp(2005, 2, 9, 8, 51, 10, 816), emptyTime, 1, 0, 0); }
private double CalcProfit(TransactionPairBinary binary, double price) { double profit; double exit; profitLoss.CalculateProfit(binary, out profit, out exit); return(profit); }
private void TryUpdateComboTrades() { if (comboTradesBinary != null && comboTradesBinary.Count > 0) { TransactionPairBinary binary = comboTradesBinary.Tail; binary.TryUpdate(model.Ticks[0]); comboTradesBinary.Tail = binary; } }
public void ProfitLossException() { pair = TransactionPairBinary.Create(); using (BinaryStore tradeData = Factory.Engine.PageStore("TradeData")) { TransactionPairsBinary tradesBinary = new TransactionPairsBinary(tradeData); tradesBinary.Add(pair); TransactionPairs trades = new TransactionPairs(null, new ProfitLossCallback(), tradesBinary); double pnl = trades.CalcProfitLoss(0); } }
public void TradeTesting() { PerformanceInner manager = TradeTickProcessing(0, 0, 30000); TransactionPairBinary expected = TransactionPairBinary.Create(); expected.Enter(1, 105.660, new TimeStamp(2005, 2, 8, 11, 57, 22, 429), emptyTime, 1, 0, 0); expected.Exit(105.670, new TimeStamp(2005, 2, 8, 11, 57, 51, 479), emptyTime, 1, 0, 0); TransactionPairs rts = manager.ComboTrades; Assert.AreEqual(-.034, Math.Round(rts.CalcProfitLoss(0), 3), "First Trade PnL"); }
public void ExitComboTrade(LogicalFill fill) { TransactionPairBinary comboTrade = comboTradesBinary.Tail; comboTrade.Exit(fill.Price, fill.Time, fill.PostedTime, model.Chart.ChartBars.BarCount, fill.OrderId, fill.OrderSerialNumber); comboTradesBinary.Tail = comboTrade; if (debug) { log.Debug("Exit Trade: " + comboTrade); } var profitLoss2 = profitLoss as ProfitLoss2; double pnl = 0D; if (profitLoss2 == null) { pnl = profitLoss.CalculateProfit(comboTrade.Direction, comboTrade.AverageEntryPrice, comboTrade.ExitPrice); } else { double costs; profitLoss2.CalculateProfit(comboTrade, out pnl, out costs); pnl = pnl - costs; } pnl = Math.Round(pnl, 2); Equity.OnChangeClosedEquity(pnl); if (trace) { log.Trace("Exit Trade: " + comboTrade); } if (tradeDebug && !model.QuietMode) { tradeLog.Debug(model.Name + "," + Equity.ClosedEquity + "," + pnl + "," + comboTrade); } if (model is Strategy) { Strategy strategy = (Strategy)model; LogicalOrder filledOrder; if (!strategy.TryGetOrderById(fill.OrderId, out filledOrder)) { throw new ApplicationException("A fill for order id: " + fill.OrderId + " was incorrectly routed to: " + strategy.Name); } if (model is Portfolio) { var portfolio = (Portfolio)model; portfolio.OnExitTrade(); } strategy.OnExitTrade(comboTrade, fill, filledOrder); } if (model is Portfolio) { var portfolio = (Portfolio)model; portfolio.OnExitTrade(); } }
public override void OnExitTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { lastMidpoint = double.NaN; direction = Direction.Sideways; fills.Clear(); SetFlatBidAsk(); if (!comboTrade.Completed) { throw new InvalidOperationException("Trade must be completed."); } totalVolume += comboTrade.Volume; }
private double CalcAveragePrice(TransactionPairBinary comboTrade) { var lots = Position.Current / lotSize; var size = Math.Abs(comboTrade.CurrentPosition); var sign = -Math.Sign(comboTrade.CurrentPosition); var openPnL = comboTrade.AverageEntryPrice * size; var closedPnl = sign * comboTrade.ClosedPoints; var result = (openPnL + closedPnl) / size; //result = comboTrade.AverageEntryPrice; return(result); }
private void TryChangeCounter(double price, int positionChange) { if (Status == InventoryStatus.Long) { if (positionChange < 0) { counter.Change(price, positionChange); } else if (counter.CurrentPosition < 0) { positionChange = Math.Min(positionChange, -counter.CurrentPosition); counter.Change(price, positionChange); var closedPoints = counter.ClosedPoints; if (closedPoints > 0) { var positionSize = Math.Abs(binary.CurrentPosition); var points = BeginningPrice * positionSize; points -= closedPoints; var newExtreme = points / positionSize; beginningPrice = newExtreme; counter.ClosedPoints = 0; } if (counter.Completed) { counter = default(TransactionPairBinary); } } } if (Status == InventoryStatus.Short) { if (positionChange > 0) { counter.Change(price, positionChange); } else if (counter.CurrentPosition > 0) { positionChange = Math.Max(positionChange, -counter.CurrentPosition); counter.Change(price, positionChange); if (counter.Completed) { var closedPoints = counter.ClosedPoints; if (closedPoints > 0) { var positionSize = Math.Abs(binary.CurrentPosition); var points = BeginningPrice * positionSize; points += closedPoints; beginningPrice = points / positionSize; } counter = default(TransactionPairBinary); } } } }
public override void OnChangeTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { lastMidpoint = double.NaN; if (fill.Position % lotSize != 0) { return; } var size = Math.Abs(comboTrade.CurrentPosition); var change = size - lastSize; totalVolume += change; lastSize = size; if (change > 0) { fills.AddFirst(new LocalFill(change, fill.Price, fill.Time)); SetupBidAsk(fill.Price); } else { change = Math.Abs(change); for (var current = fills.First; current != null; current = current.Next) { var prevFill = current.Value; if (change > prevFill.Size) { change -= prevFill.Size; fills.Remove(current); if (fills.Count > 0) { SetupBidAsk(fill.Price); } } else { prevFill.Size -= change; if (prevFill.Size == 0) { fills.Remove(current); if (fills.Count > 0) { SetupBidAsk(fill.Price); } } break; } } } }
private void ChangeComboSize(LogicalFill fill) { TransactionPairBinary combo = comboTradesBinary.Tail; combo.ChangeSize(fill.Position, fill.Price); comboTradesBinary.Tail = combo; if (model is Strategy) { Strategy strategy = (Strategy)model; LogicalOrder filledOrder; if (!strategy.TryGetOrderById(fill.OrderId, out filledOrder)) { throw new ApplicationException("A fill for order id: " + fill.OrderId + " was incorrectly routed to: " + strategy.Name); } strategy.OnChangeTrade(fill, filledOrder); } }
private void ProcessChange(TransactionPairBinary comboTrade) { var lots = (Math.Abs(comboTrade.CurrentPosition) / 1000); if (lots > maxLots) { maxLots = lots; } var extension = Math.Abs(BreakEvenPrice - midPoint); var tick = Ticks[0]; var change = comboTrade.CurrentPosition - previousPosition; if (comboTrade.CurrentPosition > 0) { BuySize = SellSize = 1000; if (comboTrade.ExitPrice < BreakEvenPrice) { offerSpread = bidSpread = startingSpread + addInventorySpread * maxLots; } else { bidSpread = offerSpread = startingSpread; } } else if (comboTrade.CurrentPosition < 0) { BuySize = SellSize = 1000; if (comboTrade.ExitPrice > BreakEvenPrice) { bidSpread = offerSpread = startingSpread + addInventorySpread * maxLots; } else { bidSpread = offerSpread = startingSpread; } } else { maxLots = 0; bidSpread = startingSpread; offerSpread = startingSpread; BuySize = SellSize = 1000; } SetBidOffer(); previousPosition = comboTrade.CurrentPosition; }
public override void OnEnterTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { lastSize = Math.Abs(comboTrade.CurrentPosition); nextIncreaseLots = 50; bestIndifferenceLine[0] = CalcIndifferencePrice(comboTrade); fills.AddFirst(new LocalFill(fill)); maxExcursionLine[0] = fill.Price; sequentialIncreaseCount = 0; lastMarketAsk = MarketAsk; lastMarketBid = MarketBid; ResetRubberBand(); maxEquity = Performance.Equity.CurrentEquity; maxDrawDown = 0D; drawDown = 0D; SetupBidAsk(fill.Price); LogFills("OnEnterTrade"); }
protected double CalcIndifferencePrice(TransactionPairBinary comboTrade) { var size = Math.Abs(comboTrade.CurrentPosition); if (size == 0) { return(midPoint); } var sign = -Math.Sign(comboTrade.CurrentPosition); var openPoints = comboTrade.AverageEntryPrice.ToLong() * size; var closedPoints = comboTrade.ClosedPoints.ToLong() * sign; var grossProfit = openPoints + closedPoints; var transaction = 0; // size * commission * sign; var expectedTransaction = 0; // size * commission * sign; var result = (grossProfit - transaction - expectedTransaction) / size; result = ((result + 5000) / 10000) * 10000; return(result.ToDouble()); }
public void EnterComboTrade(LogicalFill fill) { TransactionPairBinary pair = TransactionPairBinary.Create(); pair.Enter(fill.Position, fill.Price, fill.Time, fill.PostedTime, model.Chart.ChartBars.BarCount, fill.OrderId, fill.OrderSerialNumber); comboTradesBinary.Add(pair); if (trace) { log.Trace("Enter trade: " + pair); } if (model is Strategy) { Strategy strategy = (Strategy)model; LogicalOrder filledOrder; if (!strategy.TryGetOrderById(fill.OrderId, out filledOrder)) { throw new ApplicationException("A fill for order id: " + fill.OrderId + " was incorrectly routed to: " + strategy.Name); } strategy.OnEnterTrade(fill, filledOrder); } }
public override void OnEnterTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { switch (_State) { case TradeState.MarketSellTradeWaitFill: Log.Notice("MarketSell Trade Filled"); _State = TradeState.MarketSellTradeFilled; break; case TradeState.MarketBuyTradeWaitFill: Log.Notice("Market Buy Trade Filled"); _State = TradeState.MarketBuyTradeFilled; break; case TradeState.LimitWaitFill: if (Position.IsLong) { _State = TradeState.LimitBuyFilled; } else { _State = TradeState.LimitSellFilled; }; break; case TradeState.LimitBuyFilled: case TradeState.LimitSellFilled: _State = TradeState.LimitBuyAndSellFilled; break; default: throw new ApplicationException("Trade Entered on unknown state"); } base.OnEnterTrade(comboTrade, fill, filledOrder); }
public override void OnExitTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { switch (_State) { case TradeState.MarketSellTradeCloseing: Log.Notice("MarketSell Trade Closed"); _State = TradeState.MarketSellTradeClosed; break; case TradeState.MarketBuyTradeCloseing: Log.Notice("MarketBuy Trade Closed"); _State = TradeState.MarketBuyTradeClosed; break; case TradeState.LimitBuyFilled: case TradeState.LimitSellFilled: _State = TradeState.LimitBuyAndSellFilled; break; default: throw new ApplicationException("Trade exited on unknown state"); } base.OnExitTrade(comboTrade, fill, filledOrder); }
public override void OnChangeTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { ProcessChange(comboTrade); }
public virtual void OnCalculateProfitLoss(TransactionPairBinary trade, out double grossProfit, out double costs) { throw new NotImplementedException("The performance object ignores this method unless you override and provide your own implementation."); }
public override void OnEnterTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { lastSize = Math.Abs(comboTrade.CurrentPosition); fills.AddFirst(new LocalFill(fill)); SetupBidAsk(fill.Price); }
public void CalculateProfit(TransactionPairBinary trade, out double grossProfit, out double costs) { grossProfit = trade.ExitPrice - trade.EntryPrice + trade.ClosedPoints; costs = 0D; }
public virtual void OnExitTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { OnExitTrade(); }
public void CalculateProfit(TransactionPairBinary trade, out double grossProfit, out double costs) { costs = (slippage + commission) * symbol.FullPointValue * trade.Volume; var grossPoints = (trade.ExitPrice - trade.AverageEntryPrice) * trade.CurrentPosition + trade.ClosedPoints; grossProfit = Math.Round(grossPoints, symbol.MinimumTickPrecision) * symbol.FullPointValue; }
public override void OnChangeTrade(TransactionPairBinary comboTrade, LogicalFill fill, LogicalOrder filledOrder) { var tick = Ticks[0]; var midpoint = (tick.Ask + tick.Bid) / 2; if (!fill.IsComplete) { return; } if (Position.Size > maxTradeSize) { maxTradeSize = Position.Size; } if (comboTrade.CurrentPosition > 0 && fill.Price < maxExcursionLine[0]) { maxExcursionLine[0] = fill.Price; } if (comboTrade.CurrentPosition < 0 && fill.Price > maxExcursionLine[0]) { maxExcursionLine[0] = fill.Price; } var size = Math.Abs(comboTrade.CurrentPosition); var lots = size / lotSize; var change = size - lastSize; lastSize = size; if (change > 0) { if (enableManageRisk) { state = StrategyState.HighRisk; } var tempIndifference = CalcIndifferencePrice(comboTrade); if (Position.IsLong && tempIndifference < bestIndifferenceLine[0]) { bestIndifferenceLine[0] = tempIndifference; } if (Position.IsShort && tempIndifference > bestIndifferenceLine[0]) { bestIndifferenceLine[0] = tempIndifference; } if (lots > nextIncreaseLots) { nextIncreaseLots = (nextIncreaseLots * 3) / 2; } sequentialIncreaseCount++; var changed = false; change = Math.Abs(change); if (fills.First != null) { var firstFill = fills.First.Value; if (firstFill.Size + change <= lotSize) { firstFill.Size += change; changed = true; } } if (!changed) { fills.AddFirst(new LocalFill(change, fill.Price, fill.Time)); } SetupBidAsk(fill.Price); } else { sequentialIncreaseCount = 0; change = Math.Abs(change); var prevFill = fills.First.Value; if (change <= prevFill.Size) { prevFill.Size -= change; if (prevFill.Size == 0) { fills.RemoveFirst(); if (fills.Count > 0) { SetupBidAsk(fill.Price); } } return; } change -= prevFill.Size; fills.RemoveFirst(); SetupBidAsk(fill.Price); return; //for (var current = fills.Last; current != null; current = current.Previous) //{ // prevFill = current.Value; // if (change > prevFill.Size) // { // change -= prevFill.Size; // fills.Remove(current); // if (fills.Count > 0) // { // SetupBidAsk(fill.Price); // } // } // else // { // prevFill.Size -= change; // if (prevFill.Size == 0) // { // fills.Remove(current); // if (fills.Count > 0) // { // SetupBidAsk(fill.Price); // } // } // break; // } //} } LogFills("OnChange"); }