Skip to content

Instantly share code, notes, and snippets.

@bembengarifin
Created October 28, 2016 03:43
Show Gist options
  • Save bembengarifin/5c153657f4dedab52609be4311b829e1 to your computer and use it in GitHub Desktop.
Save bembengarifin/5c153657f4dedab52609be4311b829e1 to your computer and use it in GitHub Desktop.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Calculator
{
public class Position
{
public string Trader { get; set; }
public string Broker { get; set; }
public string Symbol { get; set; }
public int Quantity { get; set; }
}
public class BoxedPositionCalculator
{
public IEnumerable<Position> Calculate(IEnumerable<Position> positions)
{
var result = from p in positions
// use 1 for negative and 2 for positive for easier later bitwise operation
let signage = p.Quantity < 0 ? 1 : 2
// 1st group, to get a distinct trade, symbol, broker, and signage (in case there are multiple rows for same combination)
group p by new { p.Trader, p.Symbol, p.Broker, signage } into g1
// 2nd group, to group the data into just by trade and symbol, then use the broker and signage above to filter out the non boxed positions
group g1 by new { g1.Key.Trader, g1.Key.Symbol } into g2
// boxed position criteria = multiple brokers with positive and negative
where g2.Select(g => g.Key.Broker).Distinct().Count() > 1 && g2.Select(g => g.Key.signage).Distinct().Sum() == 3
select new Position
{
Trader = g2.Key.Trader,
Symbol = g2.Key.Symbol,
// minimum qty of sum positive/long positions or absolute of sum negative/short positions
Quantity = Math.Min(g2.Where(g => g.Key.signage == 2).SelectMany(g => g.Select(x => x.Quantity)).Sum(), Math.Abs(g2.Where(g => g.Key.signage == 1).SelectMany(g => g.Select(x => x.Quantity)).Sum()))
};
return result;
}
}
[TestClass]
public class BoxedTests
{
private BoxedPositionCalculator _calculator = new BoxedPositionCalculator();
[TestMethod]
public void Negative_And_Positive_Positions_With_Different_Brokers_Are_Boxed_Position()
{
var positions = new List<Position>
{
new Position { Trader = "Joe", Broker = "ML", Symbol = "IBM", Quantity = 100 },
new Position { Trader = "Joe", Broker = "DB", Symbol = "IBM", Quantity = -50 },
new Position { Trader = "Joe", Broker = "CS", Symbol = "IBM", Quantity = 30 },
new Position { Trader = "Joe", Broker = "CS", Symbol = "IBM", Quantity = 20 },
};
var result = _calculator.Calculate(positions);
Assert.AreEqual(1, result.Count());
Assert.AreEqual(50, result.Single(x => x.Trader == "Joe" && x.Symbol == "IBM").Quantity);
}
[TestMethod]
public void Only_Positive_Or_Negative_Positions_Within_Different_Brokers_Are_Not_Boxed_Position()
{
var positions = new List<Position>
{
new Position { Trader = "Joe", Broker = "ML", Symbol = "IBM", Quantity = 100 },
new Position { Trader = "Joe", Broker = "DB", Symbol = "IBM", Quantity = 50 },
new Position { Trader = "Joe", Broker = "CS", Symbol = "IBM", Quantity = 30 },
new Position { Trader = "Mike", Broker = "ML", Symbol = "IBM", Quantity = -100 },
new Position { Trader = "Mike", Broker = "DB", Symbol = "IBM", Quantity = -50 },
new Position { Trader = "Mike", Broker = "CS", Symbol = "IBM", Quantity = -30 },
};
var result = _calculator.Calculate(positions);
Assert.AreEqual(0, result.Count());
}
[TestMethod]
public void Negative_Positive_Positions_Within_Same_Broker_Are_Not_Boxed_Position()
{
var positions = new List<Position>
{
new Position { Trader = "Mike", Broker = "DB", Symbol = "IBM", Quantity = -50 },
new Position { Trader = "Mike", Broker = "DB", Symbol = "IBM", Quantity = 20 }
};
var result = _calculator.Calculate(positions);
Assert.AreEqual(0, result.Count());
}
[TestMethod]
public void Negative_Positive_Positions_Within_Same_Broker_And_Another_Position_In_Different_Broker_Are_Boxed_Position()
{
var positions = new List<Position>
{
new Position { Trader = "Mike", Broker = "DB", Symbol = "IBM", Quantity = -50 },
new Position { Trader = "Mike", Broker = "DB", Symbol = "IBM", Quantity = 20 },
new Position { Trader = "Mike", Broker = "CS", Symbol = "IBM", Quantity = 20 }
};
var result = _calculator.Calculate(positions);
Assert.AreEqual(1, result.Count());
Assert.AreEqual(40, result.Single(x => x.Trader == "Mike" && x.Symbol == "IBM").Quantity);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment