-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathOptionsChainLoadService.java
139 lines (124 loc) · 6.39 KB
/
OptionsChainLoadService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.dpgrandslam.stockdataservice.domain.service;
import com.dpgrandslam.stockdataservice.domain.error.OptionsChainLoadException;
import com.dpgrandslam.stockdataservice.domain.model.options.Option;
import com.dpgrandslam.stockdataservice.domain.model.options.OptionPriceData;
import com.dpgrandslam.stockdataservice.domain.model.options.OptionsChain;
import com.dpgrandslam.stockdataservice.domain.util.TimeUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public abstract class OptionsChainLoadService {
protected final HistoricOptionsDataService historicOptionsDataService;
protected final TimeUtils timeUtils;
/**
* Gets the a live OptionChain for a ticker that is for the closest expiration date.
* @param ticker the ticker to search
* @return the live option data for the closest expiration
*/
public abstract OptionsChain loadLiveOptionsChainForClosestExpiration(String ticker) throws OptionsChainLoadException;
/**
* Loads the full options chain (List of OptionsChain) for a ticker. A full options chain is the complete chain for
* every available expiration date.
*
* @param ticker the ticker to look for
* @return a list of OptionsChain
*/
public abstract List<OptionsChain> loadFullLiveOptionsChain(String ticker) throws OptionsChainLoadException;
/**
* Loads the live options chain for a ticker and expiration date.
*
* @param ticker the ticker to look for
* @param expirationDate the expiration date of the option
* @return the live options chain
*/
public abstract OptionsChain loadLiveOptionsChainForExpirationDate(String ticker, LocalDate expirationDate) throws OptionsChainLoadException;
/**
* Loads possible expiration dates for the option as of today.
*
* @param ticker the ticker to look for
* @return a list of expiration dates
*/
public abstract List<LocalDate> getOptionExpirationDates(String ticker) throws OptionsChainLoadException;
/**
* Loads the options chain for a specific ticker on a specific expiration date. Includes stored historic options
* date for the date range given.
*
* @param ticker the ticker to load the chain for
* @param expirationDate the expiration date to load the chain for
* @param priceDataStart the start date of historic data
* @param priceDataEnd the end date of historic data, defaults to null
* @return the OptionsChain containing the historic and live data
*/
public OptionsChain loadCompleteOptionsChainForExpirationDateWithPriceDataInRange(String ticker,
final LocalDate expirationDate,
final LocalDate priceDataStart,
final LocalDate priceDataEnd) throws OptionsChainLoadException {
OptionsChain optionsChain = new OptionsChain(ticker, expirationDate);
LocalDate finalEndDate = priceDataEnd;
LocalDate finalStartDate = priceDataStart;
if (finalEndDate == null) {
optionsChain = loadLiveOptionsChainForExpirationDate(ticker, expirationDate);
finalEndDate = LocalDate.now();
}
if (finalStartDate == null) {
finalStartDate = LocalDate.MIN;
}
List<Option> historicOptions = new ArrayList<>(historicOptionsDataService.findOptions(ticker, expirationDate, finalStartDate, finalEndDate));
optionsChain.addOptions(historicOptions);
return optionsChain;
}
/**
* Loads the options chain for a specific ticker on a specific expiration date. Includes all historic data and live data.
* @param ticker the stock ticker to load options for
* @param expirationDate the expiration date to load for
* @return the options chain
*/
public OptionsChain loadOptionsChainForExpirationDateWithAllData(String ticker, LocalDate expirationDate) throws OptionsChainLoadException {
OptionsChain liveOptionsChain = loadLiveOptionsChainForExpirationDate(ticker, expirationDate);
liveOptionsChain.addOptions(new ArrayList<>(historicOptionsDataService.findOptions(ticker, expirationDate)));
return liveOptionsChain;
}
public List<OptionsChain> loadFullOptionsChainWithAllData(String ticker) throws OptionsChainLoadException {
List<OptionsChain> fullChain = loadFullLiveOptionsChain(ticker);
combineLiveAndHistoricData(ticker, fullChain, LocalDate.MIN, LocalDate.now());
return fullChain;
}
public List<OptionsChain> loadFullOptionsChainWithAllDataBetweenDates(String ticker, LocalDate start, LocalDate end) throws OptionsChainLoadException {
List<OptionsChain> fullChain = new LinkedList<>();
if (end == null) {
end = LocalDate.now();
}
if (end.isAfter(LocalDate.now()) || end.isEqual(LocalDate.now())) {
fullChain = loadFullLiveOptionsChain(ticker);
}
if (start == null) {
start = LocalDate.MIN;
}
combineLiveAndHistoricData(ticker, fullChain, start, end);
return fullChain;
}
private void combineLiveAndHistoricData(String ticker, List<OptionsChain> fullChain, LocalDate startDate, LocalDate endDate) {
historicOptionsDataService.findOptions(ticker, startDate, endDate).forEach(option -> {
Optional<OptionsChain> found = fullChain.stream()
.filter(x -> x.getTicker().equalsIgnoreCase(option.getTicker())
&& x.getExpirationDate().equals(option.getExpiration()))
.findFirst();
if (found.isPresent()) {
found.get().addOption(option);
} else {
OptionsChain optionsChain = OptionsChain.builder()
.expirationDate(option.getExpiration())
.ticker(option.getTicker())
.build();
optionsChain.addOption(option);
fullChain.add(optionsChain);
}
});
}
}