private static List <OrderDescription> GenerateOrdersDescription(InstructionExecutionContext instructionExecutionContext, int remainingQuantityToBeExecuted, IEnumerable <MarketInfo> validMarkets, decimal requestedPrice, int availableQuantityOnMarkets) { var ordersDescription = new List <OrderDescription>(); if (remainingQuantityToBeExecuted == 1) { ordersDescription.Add(new OrderDescription(validMarkets.First(m => m.SellQuantity >= 1).MarketName, instructionExecutionContext.Way, remainingQuantityToBeExecuted, requestedPrice, instructionExecutionContext.AllowPartialExecution)); } else { var ratio = remainingQuantityToBeExecuted / (decimal)availableQuantityOnMarkets; // ReSharper disable once LoopCanBeConvertedToQuery foreach (var marketInfo in validMarkets) { var convertedMarketQuantity = Math.Round(marketInfo.SellQuantity * ratio, 2, MidpointRounding.AwayFromZero); var quantityToExecute = Convert.ToInt32(convertedMarketQuantity); if (quantityToExecute > 0) { ordersDescription.Add(new OrderDescription(marketInfo.MarketName, instructionExecutionContext.Way, quantityToExecute, requestedPrice, instructionExecutionContext.AllowPartialExecution)); } } } if (ordersDescription.Count <= 0) { throw new InvalidOperationException(string.Format("No order description has been created while there is still {0} quantity to be executed (available quantity on the market is {1}).", remainingQuantityToBeExecuted, availableQuantityOnMarkets)); } return(ordersDescription); }
protected override InstructionExecutionResult ExecuteCore(InstructionExecutionContext context) { if (context.Instruction.Data < context.Memory.Length) { context.Memory[context.Instruction.Data] = false; } return(new InstructionExecutionResult(context.ProgramCounter + 1)); }
private void RouteImpl(InstructionExecutionContext instructionExecutionContext) { // 1. Prepare the corresponding OrderBasket (via solver) var solver = new MarketSweepSolver(this.marketSnapshotProvider); var orderBasket = solver.Solve(instructionExecutionContext, this.routeOrders); // 2. Route the OrderBasket this.routeOrders.Route(orderBasket); }
public InstructionExecutionResult Execute(InstructionExecutionContext context) { if (context.Instruction.Type != Type) { throw new InvalidOperationException($"This instruction is of type {Type}, while the presented instruction is of type {context.Instruction.Type}."); } return(ExecuteCore(context)); }
private void OnOrderFailed(OrderFailedEventArgs reason, InstructionExecutionContext instructionExecutionContext) { if (instructionExecutionContext.ShouldTheInstructionBeContinued()) { this.RetryInvestorInstruction(instructionExecutionContext); } else { instructionExecutionContext.DeclareFailure(reason); } }
protected override InstructionExecutionResult ExecuteCore(InstructionExecutionContext context) { int programCounter = context.ProgramCounter + 1; if (context.Instruction.Data < context.Memory.Length) { if (context.Memory[context.Instruction.Data]) programCounter++; } return new InstructionExecutionResult(programCounter); }
public void Route(InvestorInstruction investorInstruction, Action <InvestorInstructionExecutedEventArgs> instructionExecutedCallback, Action <string> failureCallback) { // Prepares to feedback the investor var instructionExecutionContext = new InstructionExecutionContext(investorInstruction, instructionExecutedCallback, failureCallback); this.routeOrders.OrderExecuted += this.WhenOneOrderIsExecuted(instructionExecutionContext); this.routeOrders.OrderFailed += this.WhenOneOrderFailed(instructionExecutionContext); this.RouteImpl(instructionExecutionContext); this.routeOrders.OrderExecuted -= this.WhenOneOrderIsExecuted(instructionExecutionContext); this.routeOrders.OrderFailed -= this.WhenOneOrderFailed(instructionExecutionContext); }
protected override InstructionExecutionResult ExecuteCore(InstructionExecutionContext context) { if (context.Instruction.Data < context.Memory.Length) { context.Memory[context.Instruction.Data] = true; } else { throw new Exception($"Invalid memory location {context.Instruction.Data}."); } return(new InstructionExecutionResult(context.ProgramCounter + 1)); }
public void Should_Solve_with_2_markets_when_asked_quantity_is_1() { var marketA = new ApiMarketGateway("NYSE (New York)", sellQuantity: 50, sellPrice: 100M); var rejectingMarket = new ApiMarketGateway("CME (Chicago)", sellQuantity: 50, sellPrice: 100M, orderPredicate: _ => false); var marketsInvolved = new[] { marketA, rejectingMarket }; var marketGatewayAdapter = new MarketsAdapter(marketsInvolved); var investorInstruction = new InvestorInstruction(new InvestorInstructionIdentifierDto().Value, Way.Buy, quantity: 1, price: 100M, goodTill: DateTime.Now.AddMinutes(5)); var instructionExecutionContext = new InstructionExecutionContext(investorInstruction, args => { }, failure => { }); var marketSweepSolver = new MarketSweepSolver(new MarketSnapshotProvider(marketGatewayAdapter.GetAvailableMarketNames(), marketGatewayAdapter)); var orderBasket = marketSweepSolver.Solve(instructionExecutionContext, marketGatewayAdapter); Check.That(orderBasket.OrdersDescriptions.Extracting("Quantity")).ContainsExactly(1); }
public void JumpTest(int programCounterInitial, int address) { var instruction = new JumpInstruction(); var instructionModel = new InstructionModel() { Type = instruction.Type, Data = address, }; var context = new InstructionExecutionContext(new bool[0], programCounterInitial, instructionModel); var result = instruction.Execute(context); Assert.Equal(address, result.ProgramCounter); }
public void ConditionalSkipTest(int programCounterInitial, bool inputValue, int expectedProgramCounter) { var instruction = new ConditionalSkipInstruction(); var instructionModel = new InstructionModel() { Type = instruction.Type, Data = 0, }; var context = new InstructionExecutionContext(new bool[] { inputValue }, programCounterInitial, instructionModel); var result = instruction.Execute(context); Assert.Equal(expectedProgramCounter, result.ProgramCounter); }
public void ClearOutputTest(int programCounter) { var instruction = new ClearMemoryInstruction(); var instructionModel = new InstructionModel { Type = instruction.Type, Data = 0 }; var context = new InstructionExecutionContext(new bool[] { true }, programCounter, instructionModel); var result = instruction.Execute(context); Assert.False(context.Memory[0]); Assert.Equal(programCounter + 1, result.ProgramCounter); }
/// <summary> /// Build the description of the orders needed to fulfill an <see cref="SimpleOrderRouting.Infra.InvestorInstruction" /> which /// is aggregated within an <see cref="InstructionExecutionContext" /> instance. /// </summary> /// <param name="instructionExecutionContext">The <see cref="InstructionExecutionContext" /> instance that aggregates the <see cref="SimpleOrderRouting.Infra.InvestorInstruction" />.</param> /// <param name="canRouteOrders"></param> /// <returns> /// An <see cref="OrderBasket" /> containing all the orders to be routed in order to fulfill the initial <see cref="SimpleOrderRouting.Infra.InvestorInstruction" />. /// </returns> public OrderBasket Solve(InstructionExecutionContext instructionExecutionContext, ICanRouteOrders canRouteOrders) { // Checks liquidities available to weighted average for execution int remainingQuantityToBeExecuted = instructionExecutionContext.RemainingQuantityToBeExecuted; decimal requestedPrice = instructionExecutionContext.Price; var validMarkets = this.GetValidMarkets(requestedPrice); int availableQuantityOnMarkets = this.ComputeAvailableQuantityForThisPrice(validMarkets); if (availableQuantityOnMarkets == 0) { return(new OrderBasket(new List <OrderDescription>(), canRouteOrders)); } var ordersDescription = GenerateOrdersDescription(instructionExecutionContext, remainingQuantityToBeExecuted, validMarkets, requestedPrice, availableQuantityOnMarkets); return(new OrderBasket(ordersDescription, canRouteOrders)); }
private EventHandler <OrderFailedEventArgs> WhenOneOrderFailed(InstructionExecutionContext instructionExecutionContext) { // TODO: must process the message only if it's related to the proper instruction return((sender, orderFailed) => this.OnOrderFailed(orderFailed, instructionExecutionContext)); }
private EventHandler <DealExecutedEventArgs> WhenOneOrderIsExecuted(InstructionExecutionContext instructionExecutionContext) { // TODO: must process the message only if it's related to the proper instruction return((sender, dealExecuted) => instructionExecutionContext.RecordOrderExecution(dealExecuted.Quantity)); }
private void RetryInvestorInstruction(InstructionExecutionContext instructionExecutionContext) { this.RouteImpl(instructionExecutionContext); }
protected abstract InstructionExecutionResult ExecuteCore(InstructionExecutionContext context);
public void SetInstructionExecutionContextToNonNull() { executionContext = new InstructionExecutionContext(); }
protected override InstructionExecutionResult ExecuteCore(InstructionExecutionContext context) { //return new InstructionExecutionResult(context.Instruction.Data); return(new InstructionExecutionResult(context.ProgramCounter + 1)); }