From 38d333de4e31c482ef5b18b1c84916acbe6ecc6b Mon Sep 17 00:00:00 2001 From: matthewpendrey Date: Thu, 22 Oct 2020 16:38:43 +0100 Subject: [PATCH] strategy parameters on order blotter --- .../src/common/grpcUtilities.tsx | 60 +++++++++++++++++-- .../src/common/strategydescriptions.tsx | 4 +- .../src/components/Container/Container.tsx | 2 +- .../src/components/Login/Login.tsx | 2 +- .../components/OrderBlotter/OrderBlotter.tsx | 4 +- .../src/components/OrderBlotter/OrderView.ts | 25 +++++++- .../Strategies/VwapParams/VwapParamsPanel.tsx | 47 ++++++++++++--- 7 files changed, 126 insertions(+), 18 deletions(-) diff --git a/react/opentp-client/src/common/grpcUtilities.tsx b/react/opentp-client/src/common/grpcUtilities.tsx index 655f108d..72a8e97d 100644 --- a/react/opentp-client/src/common/grpcUtilities.tsx +++ b/react/opentp-client/src/common/grpcUtilities.tsx @@ -6,11 +6,61 @@ export function getGrpcErrorMessage( error : Error, prepend?: string) : string { prepend = prepend + ": " } + let grpErrorCodeAsStr = error.message switch (error.code) { - case StatusCode.PERMISSION_DENIED: - return prepend + "Permission Denied" - - default: - return prepend + error.message + case StatusCode.ABORTED: + grpErrorCodeAsStr = "Aborted" + break + case StatusCode.ALREADY_EXISTS: + grpErrorCodeAsStr = "Already Exists" + break + case StatusCode.CANCELLED: + grpErrorCodeAsStr = "Cancelled" + break + case StatusCode.DATA_LOSS: + grpErrorCodeAsStr = "Data Loss" + break + case StatusCode.DEADLINE_EXCEEDED: + grpErrorCodeAsStr = "Deadline Exceeded" + break + case StatusCode.FAILED_PRECONDITION: + grpErrorCodeAsStr = "Failed Precondition" + break + case StatusCode.INTERNAL: + grpErrorCodeAsStr = "Internal" + break + case StatusCode.INVALID_ARGUMENT: + grpErrorCodeAsStr = "Invalid Argument" + break + case StatusCode.NOT_FOUND: + grpErrorCodeAsStr = "Not Found" + break + case StatusCode.OK: + grpErrorCodeAsStr = "OK" + break + case StatusCode.OUT_OF_RANGE: + grpErrorCodeAsStr = "Out Of Range" + break + case StatusCode.PERMISSION_DENIED: + grpErrorCodeAsStr = "Permission Denied" + break + case StatusCode.RESOURCE_EXHAUSTED: + grpErrorCodeAsStr = "Resource Exhausted" + break + case StatusCode.UNAUTHENTICATED: + grpErrorCodeAsStr = "Unauthenticated" + break + case StatusCode.UNAVAILABLE: + grpErrorCodeAsStr = "Unavailable" + break + case StatusCode.UNIMPLEMENTED: + grpErrorCodeAsStr = "Unimplemented" + break + case StatusCode.UNKNOWN: + grpErrorCodeAsStr = "Unknown Host" + break + } + + return prepend + grpErrorCodeAsStr } \ No newline at end of file diff --git a/react/opentp-client/src/common/strategydescriptions.tsx b/react/opentp-client/src/common/strategydescriptions.tsx index b7a914c8..fadf522f 100644 --- a/react/opentp-client/src/common/strategydescriptions.tsx +++ b/react/opentp-client/src/common/strategydescriptions.tsx @@ -1,6 +1,8 @@ +import { Destinations } from "./destinations" + export function getStrategyDisplayName(mic: string) : string | undefined { switch(mic) { - case "XVWAP": + case Destinations.VWAP: return "VWAP STRATEGY" } diff --git a/react/opentp-client/src/components/Container/Container.tsx b/react/opentp-client/src/components/Container/Container.tsx index a6a39644..96d98259 100644 --- a/react/opentp-client/src/components/Container/Container.tsx +++ b/react/opentp-client/src/components/Container/Container.tsx @@ -1,7 +1,7 @@ import { Alignment, Button, Icon, Menu, MenuItem, Navbar, Popover, Position } from "@blueprintjs/core"; import FlexLayout, { Layout, Model, TabNode } from "flexlayout-react"; import "flexlayout-react/style/dark.css"; -import { Error, StatusCode } from "grpc-web"; +import { Error } from "grpc-web"; import React, { ReactNode } from 'react'; import log from 'loglevel'; import { ClientConfigServiceClient } from "../../serverapi/ClientconfigserviceServiceClientPb"; diff --git a/react/opentp-client/src/components/Login/Login.tsx b/react/opentp-client/src/components/Login/Login.tsx index 7d83aa83..efec2cb1 100644 --- a/react/opentp-client/src/components/Login/Login.tsx +++ b/react/opentp-client/src/components/Login/Login.tsx @@ -54,7 +54,7 @@ export default class Login extends React.Component { } if (this.serverUrl.endsWith("localhost:3000")) { - this.serverUrl = "http://127.0.0.1:32054" // for local dev, change this to point at your otp services cluster + this.serverUrl = "http://127.0.0.1:32509" // for local dev, change this to point at your otp services cluster } log.info("Connecting to services at:" + this.serverUrl) diff --git a/react/opentp-client/src/components/OrderBlotter/OrderBlotter.tsx b/react/opentp-client/src/components/OrderBlotter/OrderBlotter.tsx index 6f1361a3..8d504297 100644 --- a/react/opentp-client/src/components/OrderBlotter/OrderBlotter.tsx +++ b/react/opentp-client/src/components/OrderBlotter/OrderBlotter.tsx @@ -79,7 +79,8 @@ export default abstract class OrderBlotter

, , , - + , + ]; } @@ -96,6 +97,7 @@ export default abstract class OrderBlotter

{Array.from(this.state.orders)[row]?.getDestination()}; private renderVersion = (row: number) => {Array.from(this.state.orders)[row]?.version}; private renderOwner = (row: number) => {Array.from(this.state.orders)[row]?.owner}; + private renderParameters = (row: number) => {Array.from(this.state.orders)[row]?.parameters}; private renderStatusHeader = (row: number) => { diff --git a/react/opentp-client/src/components/OrderBlotter/OrderView.ts b/react/opentp-client/src/components/OrderBlotter/OrderView.ts index a6b8ac8a..0bf58728 100644 --- a/react/opentp-client/src/components/OrderBlotter/OrderView.ts +++ b/react/opentp-client/src/components/OrderBlotter/OrderView.ts @@ -3,6 +3,8 @@ import { Order, Side, OrderStatus } from '../../serverapi/order_pb'; import { Listing } from '../../serverapi/listing_pb'; import { ListingService } from '../../services/ListingService'; import { getStrategyDisplayName } from '../../common/strategydescriptions'; +import { Destinations } from '../../common/destinations'; +import { VwapParameters } from '../OrderTicket/Strategies/VwapParams/VwapParamsPanel'; export interface Filter { id(): string @@ -110,6 +112,7 @@ export class OrderView { owner: string; createdBy: string; errorMsg: string; + parameters: string; constructor(order: Order) { this.id = "" @@ -124,6 +127,7 @@ export class OrderView { this.owner = ""; this.errorMsg = ""; this.createdBy = ""; + this.parameters = ""; this.setOrder(order) } @@ -163,6 +167,7 @@ export class OrderView { this.owner = order.getOwnerid() this.errorMsg = order.getErrormessage() this.createdBy = order.getRootoriginatorref() + this.parameters = this.getParametersDisplayString(order) } @@ -170,6 +175,22 @@ export class OrderView { return this.order } + getParametersDisplayString(order: Order): string { + if (order.getDestination() !== "" && order.getExecparametersjson() !== "") { + + + switch (order.getDestination()) { + case Destinations.VWAP: + // order.getDestination() + ":" + order.getExecparametersjson() + let p = VwapParameters.fromJsonString(order.getExecparametersjson()) as VwapParameters + return p.toDisplayString() + } + } + + + return "" + } + getStatusString(status: OrderStatus) { switch (status) { @@ -186,8 +207,8 @@ export class OrderView { } getDestination(): string | undefined { - if( this.listing?.getMarket()?.getMic() ) { - if( this.destination === this.listing?.getMarket()?.getMic() ) { + if (this.listing?.getMarket()?.getMic()) { + if (this.destination === this.listing?.getMarket()?.getMic()) { return this.listing?.getMarket()?.getName() } } diff --git a/react/opentp-client/src/components/OrderTicket/Strategies/VwapParams/VwapParamsPanel.tsx b/react/opentp-client/src/components/OrderTicket/Strategies/VwapParams/VwapParamsPanel.tsx index b051cca2..d883fa13 100644 --- a/react/opentp-client/src/components/OrderTicket/Strategies/VwapParams/VwapParamsPanel.tsx +++ b/react/opentp-client/src/components/OrderTicket/Strategies/VwapParams/VwapParamsPanel.tsx @@ -2,6 +2,8 @@ import * as React from "react"; import { Checkbox, Label, NumericInput } from "@blueprintjs/core"; import { TimePicker, TimePrecision } from "@blueprintjs/datetime"; import { StrategyPanel } from "../../OrderTicket"; +import { Destinations } from "../../../../common/destinations"; + export interface Props { children?: React.ReactNode @@ -40,17 +42,19 @@ export default class VwapParamsPanel extends React.Component imple } getDestination(): string { - return "XVWAP" + return Destinations.VWAP } getParamsString(): string { + var params : VwapParameters; if (this.state.setBuckets) { - return JSON.stringify(new VwapParameters(Math.floor(this.startTime.getTime() / 1000), Math.floor(this.endTime.getTime() / 1000), this.buckets)) + params = new VwapParameters(Math.floor(this.startTime.getTime() / 1000), Math.floor(this.endTime.getTime() / 1000), this.buckets) } else { - return JSON.stringify(new VwapParameters(Math.floor(this.startTime.getTime() / 1000), Math.floor(this.endTime.getTime() / 1000))) + params = new VwapParameters(Math.floor(this.startTime.getTime() / 1000), Math.floor(this.endTime.getTime() / 1000)) } + return params.toJsonString() } render() { @@ -88,10 +92,7 @@ export default class VwapParamsPanel extends React.Component imple } - - - -class VwapParameters { +export class VwapParameters { utcStartTimeSecs: number; utcEndTimeSecs: number; buckets?: number; @@ -103,6 +104,38 @@ class VwapParameters { this.utcEndTimeSecs = utcEndTimeSecs; this.buckets = buckets; } + + + + static fromJsonString(jsonString : string) : VwapParameters { + let p = JSON.parse(jsonString) as VwapParameters + + return new VwapParameters(p.utcStartTimeSecs, p.utcEndTimeSecs, p.buckets) + } + + + toJsonString() : string { + return JSON.stringify(this) + } + + toDisplayString() : string { + + var d = new Date(0); // The 0 there is the key, which sets the date to the epoch + d.setUTCSeconds(this.utcStartTimeSecs); + + + let result = "Start:" + d.toLocaleTimeString() + d = new Date(0); + d.setUTCSeconds(this.utcEndTimeSecs); + result += " End:" + d.toLocaleTimeString() + + if( this.buckets ) { + result += " Buckets:" + this.buckets + } + + return result + } + }