Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/ScottLogic/finos-vuu into S…
Browse files Browse the repository at this point in the history
…LVUU-117-type-guard-for-layout
  • Loading branch information
vferraro-scottlogic committed Jan 11, 2024
2 parents cd66125 + 7743733 commit 21f2303
Show file tree
Hide file tree
Showing 118 changed files with 3,441 additions and 859 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ object BasketModule extends DefaultModule {
joinColumns = Columns.allFrom(tableDefs.get(NAME, BasketTradingConstituentTable)) ++ Columns.allFromExcept(tableDefs.get(PriceModule.NAME, "prices"), "ric"),
joins =
JoinTo(
table = tableDefs.get(PriceModule.NAME, "prices"),
table = tableDefs.get(PriceModule.NAME, PriceModule.PriceTable),
joinSpec = JoinSpec(left = "ric", right = "ric", LeftOuterJoin)
),
joinFields = Seq(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@ import org.finos.toolbox.time.Clock
import org.finos.vuu.core.module.basket.BasketConstants.Side
import org.finos.vuu.core.module.basket.BasketModule
import org.finos.vuu.core.module.basket.BasketModule.BasketConstituentTable
import org.finos.vuu.core.table.{DataTable, RowData, RowWithData, TableContainer}
import org.finos.vuu.core.module.price.PriceModule
import org.finos.vuu.core.table.{DataTable, EmptyRowData, RowData, RowWithData, TableContainer}
import org.finos.vuu.net.rpc.RpcHandler
import org.finos.vuu.net.RequestContext
import org.finos.vuu.order.oms.OmsApi
import org.finos.vuu.viewport._

import java.util.concurrent.atomic.AtomicInteger

object BasketTradeId {

private val counter: AtomicInteger = new AtomicInteger(0)
def oneNew(user:String): String = {

def oneNew(user: String): String = {
val counterValue = counter.incrementAndGet()
user + "-" + "".padTo(5 - counterValue.toString.length, "0").mkString + counterValue
}
}

trait BasketServiceIF{
trait BasketServiceIF {
def createBasket(basketId: String, name: String)(ctx: RequestContext): ViewPortAction
}

Expand All @@ -32,11 +35,11 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer, va
private def getConstituentsForSourceBasket(basketId: String): List[RowData] = {
val table = tableContainer.getTable(BasketConstituentTable)
val keys = table.primaryKeys.toList
keys.map( key => table.pullRow(key) ).filter(_.get(BC.BasketId).toString == basketId)
keys.map(key => table.pullRow(key)).filter(_.get(BC.BasketId).toString == basketId)
}

private def mkTradingConstituentRow(side: String, sourceBasketId: String, basketTradeInstanceId: String, constituentKey: String,
quantity: Long, weighting: Double, basketConsRow: RowData): RowWithData = {
quantity: Long, weighting: Double, limitPrice: Option[Double], basketConsRow: RowData): RowWithData = {
RowWithData(
constituentKey,
Map(
Expand All @@ -49,6 +52,7 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer, va
BTC.Side -> side,
BTC.Weighting -> weighting,
BTC.PriceStrategyId -> 2,
BTC.LimitPrice -> limitPrice.orNull,
BTC.Algo -> -1,
BTC.OrderStatus -> OrderStates.PENDING,
BTC.FilledQty -> 0
Expand All @@ -70,19 +74,33 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer, va
logger.error("Cannot find the Basket Trading table.")
}

val priceTable = tableContainer.getTable(PriceModule.PriceTable)
tableContainer.getTable(BasketModule.BasketTradingConstituentTable) match {
case table: DataTable =>
constituents.foreach( rowData => {
val constituentKey = basketTradeId + "." + rowData.get(BTC.Ric)
constituents.foreach(rowData => {
val ric = rowData.get(BTC.Ric).toString
val constituentKey = s"$basketTradeId.$ric"
val weighting = rowData.get(BTC.Weighting).asInstanceOf[Double]
val quantity = (weighting * 100).asInstanceOf[Long]
val side = rowData.get(BTC.Side).toString
table.processUpdate(constituentKey, mkTradingConstituentRow(side, sourceBasketId, basketTradeId, constituentKey, quantity, weighting, rowData), clock.now())
val limitPrice = getLastPrice(priceTable, ric)
table.processUpdate(constituentKey, mkTradingConstituentRow(side, sourceBasketId, basketTradeId, constituentKey, quantity, weighting, limitPrice, rowData), clock.now())
})
case null =>
logger.error("Cannot find the Basket Trading Constituent.")
}

ViewPortCreateSuccess(basketTradeId)
}

private def getLastPrice(priceTable: DataTable, ric: String): Option[Double] = {
priceTable.pullRow(ric) match {
case row: RowWithData =>
row.get("last") match {
case null => None
case price: Double => Some(price)
}
case EmptyRowData => None
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.finos.toolbox.lifecycle.LifecycleContainer
import org.finos.toolbox.time.{Clock, TestFriendlyClock}
import org.finos.vuu.api.ViewPortDef
import org.finos.vuu.core.module.TableDefContainer
import org.finos.vuu.core.module.basket.BasketModule.{BasketColumnNames => B, BasketConstituentColumnNames => BC}
import org.finos.vuu.core.module.basket.service.{BasketServiceIF, BasketTradeId, BasketTradingServiceIF}
import org.finos.vuu.core.module.price.PriceModule
import org.finos.vuu.order.oms.OmsApi
Expand Down Expand Up @@ -32,46 +33,73 @@ class BasketCreateTest extends VuuServerTestCase {
vuuServer =>

vuuServer.login("testUser", "testToken")
val basketId = ".FTSE"

vuuServer.overrideViewPortDef("prices", (table, _, _, _) => ViewPortDef(table.getTableDef.columns, null))

val pricesProvider = vuuServer.getProvider(PriceModule.NAME, "prices")
val pricesProvider = vuuServer.getProvider(PriceModule.NAME, PriceModule.PriceTable)
val basketProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketTable)
val constituentProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketConstituentTable)

pricesProvider.tick("VOD.L", Map("ric" -> "VOD.L", "phase" -> "C"))
basketProvider.tick(basketId, Map(B.Id -> basketId, B.Name -> ".FTSE 100", B.NotionalValue -> 1000001, B.NotionalValueUsd -> 1500001))

val viewport = vuuServer.createViewPort(PriceModule.NAME, "prices")
//given constituent with price
constituentProvider.tick(s"VOD.L.$basketId", Map(BC.RicBasketId -> s"VOD.L.$basketId", BC.Ric -> "VOD.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Vodafone"))
pricesProvider.tick("VOD.L", Map("ric" -> "VOD.L", "bid" -> 1.3, "ask" -> 1.6, "last" -> 1.5, "phase" -> "C"))

//given constituent with no price
constituentProvider.tick(s"BT.L.$basketId", Map(BC.RicBasketId -> s"BT.L.$basketId", BC.Ric -> "BT.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "SELL", BC.Description -> "British Telecom"))

//given constituent with price but missing last price
constituentProvider.tick(s"BP.L.$basketId", Map(BC.RicBasketId -> s"BP.L.$basketId", BC.Ric -> "BP.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Beyond Petroleum"))
pricesProvider.tick("BP.L", Map("ric" -> "BP.L", "bid" -> 5.3, "phase" -> "C"))

val viewportPrices = vuuServer.createViewPort(PriceModule.NAME, "prices")

vuuServer.runOnce()

assertVpEq(combineQsForVp(viewport)) {
assertVpEq(combineQsForVp(viewportPrices)) {
Table(
("ric", "bid", "ask", "bidSize", "askSize", "last", "open", "close", "phase", "scenario"),
("VOD.L", null, null, null, null, null, null, null, "C", null)
("BP.L", 5.3, null, null, null, null, null, null, "C", null),
("VOD.L", 1.3, 1.6, null, null, 1.5, null, null, "C", null),
)
}

val viewportBasket = vuuServer.createViewPort(BasketModule.NAME, BasketTable)

val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](viewportBasket)

val vpAction = basketService.createBasket(".FTSE", "TestBasket")(vuuServer.requestContext)

val vpAction = basketService.createBasket(basketId, "TestBasket")(vuuServer.requestContext)
vuuServer.runOnce()
assert(vpAction.isInstanceOf[ViewPortCreateSuccess])
val basketTradeInstanceId = vpAction.asInstanceOf[ViewPortCreateSuccess].key

val viewportBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable)
val viewportBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable)

val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](viewportBasketTrading)

//CJS: I don't like this forced cast, need to look at that a bit
basketTradingService.editCellAction().func(basketTradeInstanceId, BT.Units, 100.asInstanceOf[Object], viewportBasketTrading, vuuServer.session)

vuuServer.runOnce()
Then("get all the updates that have occurred for all view ports from the outbound queue")
val updates = combineQs(viewportBasketTrading)

assertVpEq(filterByVp(viewportBasketTrading, updates)) {
Table(
("instanceId", "basketId", "basketName", "units", "status", "filledPct", "totalNotionalUsd", "totalNotional", "fxRateToUsd", "side"),
(basketTradeInstanceId, ".FTSE", "TestBasket", 100, "OFF-MARKET", null, null, null, null, "BUY")
)
}

assertVpEq(combineQsForVp(viewportBasketTrading)) {
assertVpEq(filterByVp(viewportBasketTradingCons, updates)) {
Table(
("basketId", "instanceId", "basketName", "units", "status", "filledPct", "totalNotionalUsd", "totalNotional", "fxRateToUsd", "side"),
(".FTSE", basketTradeInstanceId, "TestBasket", 100, "OFF-MARKET", null, null, null, null, "BUY")
("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, 1.5, 2, 0, "PENDING"),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class BasketMutateOffMarketTest extends VuuServerTestCase {
assertVpEq(combineQsForVp(vpBasketTradingCons)) {
Table(
("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING")
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, 301.5, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, 201.5, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, 101.5, 2, 0, "PENDING")
)
}

Expand All @@ -120,9 +120,9 @@ class BasketMutateOffMarketTest extends VuuServerTestCase {
assertVpEq(filterByVp(vpBasketTradingCons, updates)) {
Table(
("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING")
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, 301.5, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, 201.5, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, 101.5, 2, 0, "PENDING")
)
}

Expand All @@ -133,9 +133,9 @@ class BasketMutateOffMarketTest extends VuuServerTestCase {
assertVpEq(filterByVp(vpBasketTradingCons, combineQs(vpBasketTrading))) {
Table(
("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"),
(100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(100L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING")
(100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, 301.5, 2, 0, "PENDING"),
(100L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, 201.5, 2, 0, "PENDING"),
(100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, 101.5, 2, 0, "PENDING")
)
}
}
Expand Down Expand Up @@ -235,12 +235,12 @@ class BasketMutateOffMarketTest extends VuuServerTestCase {

def GivenBasketTradeExist(vuuServer: TestVuuServer, basketId: String, basketTradeName: String): String = {
val basketProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketTable)
basketProvider.tick(".FTSE", Map(B.Id -> ".FTSE", B.Name -> ".FTSE 100", B.NotionalValue -> 1000001, B.NotionalValueUsd -> 1500001))
basketProvider.tick(basketId, Map(B.Id -> basketId, B.Name -> ".FTSE 100", B.NotionalValue -> 1000001, B.NotionalValueUsd -> 1500001))

val constituentProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketConstituentTable)
constituentProvider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Vodafone"))
constituentProvider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "SELL", BC.Description -> "British Telecom"))
constituentProvider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Beyond Petroleum"))
constituentProvider.tick(s"VOD.L.$basketId", Map(BC.RicBasketId -> s"VOD.L.$basketId", BC.Ric -> "VOD.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Vodafone"))
constituentProvider.tick(s"BT.L.$basketId", Map(BC.RicBasketId -> s"BT.L.$basketId", BC.Ric -> "BT.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "SELL", BC.Description -> "British Telecom"))
constituentProvider.tick(s"BP.L.$basketId", Map(BC.RicBasketId -> s"BP.L.$basketId", BC.Ric -> "BP.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Beyond Petroleum"))

val vpBasket = vuuServer.createViewPort(BasketModule.NAME, BasketModule.BasketTable)
val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](vpBasket)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ class BasketSendToMarketTest extends VuuServerTestCase {
assertVpEq(combineQsForVp(vpBasketTradingCons)) {
Table(
("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING")
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, 301.5, 2, 0, "PENDING"),
(10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, 201.5, 2, 0, "PENDING"),
(10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, 101.5, 2, 0, "PENDING")
)
}

Expand Down
Loading

0 comments on commit 21f2303

Please sign in to comment.