Created
October 28, 2016 03:43
-
-
Save bembengarifin/5c153657f4dedab52609be4311b829e1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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