|
1 | 1 |
|
2 | 2 | import * as _ from 'lodash'; |
| 3 | +import axios from 'axios'; |
| 4 | + |
3 | 5 | import PortfolioService from '../portfolio/portfolio.service'; |
4 | 6 | import portfolioController from '../portfolio/portfolio.controller'; |
5 | 7 |
|
| 8 | +import * as configurations from '../../config/environment'; |
| 9 | + |
| 10 | +const dataServiceUrl = configurations.apps.goliath; |
| 11 | + |
6 | 12 | export interface MonthlyStrategyList { |
7 | | - month: string; |
8 | | - year: number; |
9 | | - day: number; |
10 | | - daysToExp: number; |
11 | | - secondaryMonth: string; |
12 | | - secondaryYear: number; |
13 | | - secondaryDay: number; |
14 | | - secondaryDaysToExp: number; |
15 | | - type: string; |
16 | | - secondaryType: string; |
17 | | - leap: boolean; |
18 | | - optionStrategyList: Strategy[]; |
| 13 | + month: string; |
| 14 | + year: number; |
| 15 | + day: number; |
| 16 | + daysToExp: number; |
| 17 | + secondaryMonth: string; |
| 18 | + secondaryYear: number; |
| 19 | + secondaryDay: number; |
| 20 | + secondaryDaysToExp: number; |
| 21 | + type: string; |
| 22 | + secondaryType: string; |
| 23 | + leap: boolean; |
| 24 | + optionStrategyList: Strategy[]; |
19 | 25 | } |
20 | 26 |
|
21 | 27 | export interface Strategy { |
22 | | - primaryLeg: Option; |
23 | | - secondaryLeg: Option; |
24 | | - strategyStrike: number; |
25 | | - strategyBid: number; |
26 | | - strategyAsk: number; |
| 28 | + primaryLeg: Option; |
| 29 | + secondaryLeg: Option; |
| 30 | + strategyStrike: number; |
| 31 | + strategyBid: number; |
| 32 | + strategyAsk: number; |
27 | 33 | } |
28 | 34 |
|
29 | 35 | export interface Option { |
| 36 | + symbol: string; |
| 37 | + putCallInd: string; |
| 38 | + description: string; |
| 39 | + bid: number; |
| 40 | + ask: number; |
| 41 | + range: string; |
| 42 | + strikePrice: number; |
| 43 | + totalVolume: number; |
| 44 | +} |
| 45 | + |
| 46 | +export interface OptionsChain { |
| 47 | + symbol: string; |
| 48 | + underlying: { |
30 | 49 | symbol: string; |
31 | | - putCallInd: string; |
32 | 50 | description: string; |
| 51 | + change: number; |
| 52 | + percentChange: number; |
| 53 | + close: number; |
33 | 54 | bid: number; |
34 | 55 | ask: number; |
35 | | - range: string; |
36 | | - strikePrice: number; |
| 56 | + last: number; |
| 57 | + mark: number; |
| 58 | + markChange: number; |
| 59 | + markPercentChange: number; |
| 60 | + bidSize: number; |
| 61 | + askSize: number; |
| 62 | + highPrice: number; |
| 63 | + lowPrice: number; |
| 64 | + openPrice: number; |
37 | 65 | totalVolume: number; |
38 | | -} |
39 | | - |
40 | | -export interface OptionsChain { |
41 | | - symbol: string; |
42 | | - underlying: { |
43 | | - symbol: string; |
44 | | - description: string; |
45 | | - change: number; |
46 | | - percentChange: number; |
47 | | - close: number; |
48 | | - bid: number; |
49 | | - ask: number; |
50 | | - last: number; |
51 | | - mark: number; |
52 | | - markChange: number; |
53 | | - markPercentChange: number; |
54 | | - bidSize: number; |
55 | | - askSize: number; |
56 | | - highPrice: number; |
57 | | - lowPrice: number; |
58 | | - openPrice: number; |
59 | | - totalVolume: number; |
60 | | - fiftyTwoWeekHigh: number; |
61 | | - fiftyTwoWeekLow: number; |
62 | | - }; |
63 | | - monthlyStrategyList: MonthlyStrategyList[]; |
| 66 | + fiftyTwoWeekHigh: number; |
| 67 | + fiftyTwoWeekLow: number; |
| 68 | + }; |
| 69 | + monthlyStrategyList: MonthlyStrategyList[]; |
64 | 70 | } |
65 | 71 |
|
66 | 72 | export interface ImpliedMove { |
67 | | - move: number; |
68 | | - upperPrice: number; |
69 | | - lowerPrice: number; |
70 | | - strategy: Strategy; |
| 73 | + move: number; |
| 74 | + upperPrice: number; |
| 75 | + lowerPrice: number; |
| 76 | + strategy: Strategy; |
71 | 77 | } |
72 | 78 |
|
73 | 79 | class OptionService { |
74 | | - calculateImpliedMove(accountId, symbol, strikeCount, optionType, minExpiration = 29) { |
75 | | - return PortfolioService.getOptionsStraddle(accountId, symbol, strikeCount, optionType) |
76 | | - .then((straddleOptionsChain: OptionsChain) => { |
77 | | - const strategyList = straddleOptionsChain.monthlyStrategyList.find(element => element.daysToExp >= minExpiration); |
78 | | - const goal = straddleOptionsChain.underlying.last; |
79 | | - |
80 | | - const closestStrikeStraddle = strategyList.optionStrategyList.reduce((prev, curr) => { |
81 | | - return (Math.abs(curr.strategyStrike - goal) < Math.abs(prev.strategyStrike - goal) ? curr : prev); |
82 | | - }); |
83 | | - |
84 | | - const strategyCost = portfolioController.midPrice(closestStrikeStraddle.strategyAsk, closestStrikeStraddle.strategyBid); |
85 | | - const move = _.round(strategyCost / goal, 3); |
86 | | - const movePrice = _.round(move * goal, 2); |
87 | | - |
88 | | - return { |
89 | | - move, |
90 | | - upperPrice: _.round(goal + movePrice, 2), |
91 | | - lowerPrice: _.round(goal - movePrice, 2), |
92 | | - strategyCost, |
93 | | - strategy: closestStrikeStraddle |
94 | | - }; |
95 | | - }); |
| 80 | + calculateImpliedMove(accountId, symbol, strikeCount, optionType, minExpiration = 29) { |
| 81 | + return PortfolioService.getOptionsStraddle(accountId, symbol, strikeCount, optionType) |
| 82 | + .then((straddleOptionsChain: OptionsChain) => { |
| 83 | + const strategyList = straddleOptionsChain.monthlyStrategyList.find(element => element.daysToExp >= minExpiration); |
| 84 | + const goal = straddleOptionsChain.underlying.last; |
| 85 | + |
| 86 | + const closestStrikeStraddle = strategyList.optionStrategyList.reduce((prev, curr) => { |
| 87 | + return (Math.abs(curr.strategyStrike - goal) < Math.abs(prev.strategyStrike - goal) ? curr : prev); |
| 88 | + }); |
| 89 | + |
| 90 | + const strategyCost = portfolioController.midPrice(closestStrikeStraddle.strategyAsk, closestStrikeStraddle.strategyBid); |
| 91 | + const move = _.round(strategyCost / goal, 3); |
| 92 | + const movePrice = _.round(move * goal, 2); |
| 93 | + |
| 94 | + this.saveImpliedMove(symbol, move); |
| 95 | + return { |
| 96 | + move, |
| 97 | + upperPrice: _.round(goal + movePrice, 2), |
| 98 | + lowerPrice: _.round(goal - movePrice, 2), |
| 99 | + strategyCost, |
| 100 | + strategy: closestStrikeStraddle |
| 101 | + }; |
| 102 | + }); |
| 103 | + } |
| 104 | + |
| 105 | + private saveImpliedMove(symbol: string, move: number) { |
| 106 | + |
| 107 | + if (move) { |
| 108 | + axios.post(`${dataServiceUrl}backtest/update-implied-move`, { |
| 109 | + symbol, |
| 110 | + impliedMove: move |
| 111 | + }); |
96 | 112 | } |
| 113 | + } |
97 | 114 | } |
98 | 115 |
|
99 | 116 | export default new OptionService(); |
0 commit comments