-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from pagh2322/feat/11
Feat/11
- Loading branch information
Showing
99 changed files
with
3,485 additions
and
1,037 deletions.
There are no files selected for viewing
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
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
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
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
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
50 changes: 50 additions & 0 deletions
50
src/main/java/org/mockInvestment/backTest/api/BackTestApi.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.mockInvestment.backTest.api; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.mockInvestment.backTest.application.BackTestCrossStrategyService; | ||
import org.mockInvestment.backTest.application.BackTestRSIStrategyService; | ||
import org.mockInvestment.backTest.dto.request.CrossStrategyRequest; | ||
import org.mockInvestment.backTest.dto.request.RSIStrategyRequest; | ||
import org.mockInvestment.backTest.dto.response.BackTestResultResponse; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.time.LocalDate; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/back_test") | ||
public class BackTestApi { | ||
|
||
private final BackTestRSIStrategyService backTestRSIStrategyService; | ||
|
||
private final BackTestCrossStrategyService backTestCrossStrategyService; | ||
|
||
|
||
@GetMapping("/rsi") | ||
public ResponseEntity<BackTestResultResponse> backTestUsingRSIStrategy( | ||
@RequestParam("code") String stockCode, | ||
@RequestParam("start") LocalDate startDate, | ||
@RequestParam("end") LocalDate endDate, | ||
@RequestParam("buyRSI") double buyRSI, | ||
@RequestParam("sellRSI") double sellRSI, | ||
@RequestParam("amount") double amount | ||
) { | ||
RSIStrategyRequest request = new RSIStrategyRequest(stockCode, startDate, endDate, buyRSI, sellRSI, amount); | ||
BackTestResultResponse response = backTestRSIStrategyService.runTest(request); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@GetMapping("/cross") | ||
public ResponseEntity<BackTestResultResponse> backTestUsingCrossStrategy( | ||
@RequestParam("code") String stockCode, | ||
@RequestParam("start") LocalDate startDate, | ||
@RequestParam("end") LocalDate endDate, | ||
@RequestParam("amount") double amount | ||
) { | ||
CrossStrategyRequest request = new CrossStrategyRequest(true, true, stockCode, startDate, endDate, amount); | ||
BackTestResultResponse response = backTestCrossStrategyService.runTest(request); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
} |
82 changes: 82 additions & 0 deletions
82
src/main/java/org/mockInvestment/backTest/application/BackTestCrossStrategyService.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package org.mockInvestment.backTest.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.mockInvestment.backTest.dto.request.CrossStrategyRequest; | ||
import org.mockInvestment.backTest.dto.response.BackTestResultResponse; | ||
import org.mockInvestment.backTest.dto.response.BackTestTradeHistory; | ||
import org.mockInvestment.stockPrice.application.StockPriceCandleFindService; | ||
import org.mockInvestment.stockPrice.domain.StockPriceCandle; | ||
import org.mockInvestment.stockPrice.repository.StockPriceCandleRepository; | ||
import org.mockInvestment.stockPrice.util.PeriodExtractor; | ||
import org.mockInvestment.stockTicker.domain.StockTicker; | ||
import org.mockInvestment.stockTicker.exception.StockTickerNotFoundException; | ||
import org.mockInvestment.stockTicker.repository.StockTickerRepository; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDate; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class BackTestCrossStrategyService { | ||
|
||
private final StockTickerRepository stockTickerRepository; | ||
|
||
private final StockPriceCandleRepository stockPriceCandleRepository; | ||
|
||
private final StockPriceCandleFindService stockPriceCandleFindService; | ||
|
||
|
||
public BackTestResultResponse runTest(CrossStrategyRequest request) { | ||
StockTicker stockTicker = stockTickerRepository.findByCode(request.stockCode()) | ||
.orElseThrow(StockTickerNotFoundException::new); | ||
List<BackTestTradeHistory> histories = new ArrayList<>(); | ||
LocalDate startDate = request.startDate(); | ||
while (startDate.isBefore(request.endDate())) { | ||
PeriodExtractor periodExtractor = new PeriodExtractor(startDate, "6m"); | ||
List<StockPriceCandle> stockPriceCandles = stockPriceCandleFindService.findStockPriceCandles(stockTicker, periodExtractor); | ||
|
||
double currentPrice = stockPriceCandles.get(stockPriceCandles.size() - 1).getClose(); | ||
|
||
if (histories.isEmpty()) { | ||
histories.add(BackTestTradeHistory.of(true, currentPrice, request.amount(), null, startDate)); | ||
startDate = getNextMarketDate(startDate); | ||
continue; | ||
} | ||
|
||
double[] macd = TechnicalIndicatorCalculator.calculateMACD(stockPriceCandles); | ||
double[] signalLine = TechnicalIndicatorCalculator.calculateSignalLine(macd); | ||
|
||
BackTestTradeHistory lastOrder = histories.get(histories.size() - 1); | ||
double amount = calcAmount(lastOrder.amount(), lastOrder.price(), currentPrice); | ||
|
||
double currentMACD = macd[macd.length - 2]; | ||
double currentSignalLine = signalLine[signalLine.length - 2]; | ||
double previousMACD = macd[macd.length - 3]; | ||
double previousSignalLine = signalLine[signalLine.length - 3]; | ||
|
||
if (currentMACD > currentSignalLine && previousMACD < previousSignalLine) { | ||
if (!lastOrder.buy()) | ||
histories.add(BackTestTradeHistory.of(true, currentPrice, amount, "Golden", startDate)); | ||
} else if (currentMACD < currentSignalLine && previousMACD > previousSignalLine) { | ||
if (lastOrder.buy()) | ||
histories.add(BackTestTradeHistory.of(false, currentPrice, amount, "Dead", startDate)); | ||
} | ||
startDate = getNextMarketDate(startDate); | ||
} | ||
return new BackTestResultResponse(histories); | ||
} | ||
|
||
private double calcAmount(double previousAmount, double previousPrice, double currentPrice) { | ||
return previousAmount * (currentPrice / previousPrice); | ||
} | ||
|
||
private LocalDate getNextMarketDate(LocalDate previousDate) { | ||
List<LocalDate> dates = stockPriceCandleRepository.findCandidateDates(previousDate, PageRequest.of(0, 2)); | ||
return dates.get(1); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/main/java/org/mockInvestment/backTest/application/BackTestRSIStrategyService.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package org.mockInvestment.backTest.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.mockInvestment.backTest.dto.request.RSIStrategyRequest; | ||
import org.mockInvestment.backTest.dto.response.BackTestResultResponse; | ||
import org.mockInvestment.backTest.dto.response.BackTestTradeHistory; | ||
import org.mockInvestment.stockPrice.application.StockPriceCandleFindService; | ||
import org.mockInvestment.stockPrice.domain.StockPriceCandle; | ||
import org.mockInvestment.stockPrice.repository.StockPriceCandleRepository; | ||
import org.mockInvestment.stockPrice.util.PeriodExtractor; | ||
import org.mockInvestment.stockTicker.domain.StockTicker; | ||
import org.mockInvestment.stockTicker.exception.StockTickerNotFoundException; | ||
import org.mockInvestment.stockTicker.repository.StockTickerRepository; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDate; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class BackTestRSIStrategyService { | ||
|
||
private final StockTickerRepository stockTickerRepository; | ||
|
||
private final StockPriceCandleRepository stockPriceCandleRepository; | ||
|
||
private final StockPriceCandleFindService stockPriceCandleFindService; | ||
|
||
|
||
public BackTestResultResponse runTest(RSIStrategyRequest request) { | ||
StockTicker stockTicker = stockTickerRepository.findByCode(request.stockCode()) | ||
.orElseThrow(StockTickerNotFoundException::new); | ||
List<BackTestTradeHistory> histories = new ArrayList<>(); | ||
LocalDate startDate = request.startDate(); | ||
while (startDate.isBefore(request.endDate())) { | ||
PeriodExtractor periodExtractor = new PeriodExtractor(startDate, "6m"); | ||
List<StockPriceCandle> stockPriceCandles = stockPriceCandleFindService.findStockPriceCandles(stockTicker, periodExtractor); | ||
double rsi = TechnicalIndicatorCalculator.calculateRSI(stockPriceCandles); | ||
double currentPrice = stockPriceCandles.get(stockPriceCandles.size() - 1).getClose(); | ||
|
||
if (histories.isEmpty()) { | ||
histories.add(BackTestTradeHistory.of(true, currentPrice, request.amount(), rsi, startDate)); | ||
startDate = getNextMarketDate(startDate); | ||
continue; | ||
} | ||
|
||
BackTestTradeHistory lastOrder = histories.get(histories.size() - 1); | ||
double amount = calcAmount(lastOrder.amount(), lastOrder.price(), currentPrice); | ||
if (rsi >= request.sellRSI()) { // should sell | ||
if (lastOrder.buy()) | ||
histories.add(BackTestTradeHistory.of(false, currentPrice, amount, rsi, startDate)); | ||
} | ||
else if (rsi <= request.buyRSI()) { // should buy | ||
if (!lastOrder.buy()) | ||
histories.add(BackTestTradeHistory.of(true, currentPrice, amount, rsi, startDate)); | ||
} | ||
startDate = getNextMarketDate(startDate); | ||
} | ||
return new BackTestResultResponse(histories); | ||
} | ||
|
||
private double calcAmount(double previousAmount, double previousPrice, double currentPrice) { | ||
return previousAmount * (currentPrice / previousPrice); | ||
} | ||
|
||
private LocalDate getNextMarketDate(LocalDate previousDate) { | ||
List<LocalDate> dates = stockPriceCandleRepository.findCandidateDates(previousDate, PageRequest.of(0, 2)); | ||
return dates.get(1); | ||
} | ||
|
||
} |
Oops, something went wrong.