Merge branch 'feature/kline-alternate-source' into 'develop'

Add alternate source

See merge request india/india_market_java!43
This commit is contained in:
Gavin g
2024-09-26 09:57:06 +00:00
3 changed files with 88 additions and 75 deletions

View File

@@ -60,6 +60,10 @@ public class MoneyStockPO {
* NSE India的id */
String nseIndiaId;
/**
* NSE India Chart的id */
String nseIndiaChartId;
/**
* 自有self_url */
String selfUrl;

View File

@@ -2,18 +2,21 @@ package cn.stock.market.utils;
import cn.stock.market.dto.StockHistoryRequest;
import cn.stock.market.dto.StockHistoryResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NseIndiaRequest {
private static final String NSE_INDIA_URL = "https://www.nseindia.com";
private static final String NSE_INDIA_CHART_URL = "https://charting.nseindia.com";
private static final OkHttpClient client;
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
client = new OkHttpClient.Builder()
@@ -47,8 +50,8 @@ public class NseIndiaRequest {
return request;
}
private static void initCookie() {
Request request = createRequest(NSE_INDIA_URL);
private static void initCookie(String url) {
Request request = createRequest(url);
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to fetch initial cookies");
@@ -58,8 +61,35 @@ public class NseIndiaRequest {
}
}
private static Integer getCode(String symbol) {
Request request = createRequest(NSE_INDIA_CHART_URL + "//Charts/GetEQMasters").newBuilder()
.addHeader("referer", NSE_INDIA_CHART_URL)
.addHeader("origin", NSE_INDIA_CHART_URL)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to get EQ code");
}
String result = response.body().string();
String regex = "(\\d+)\\|" + symbol + "\\|.*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(result);
if (matcher.find()) {
return Integer.valueOf(matcher.group(1));
}
throw new IOException("No data found");
} catch (IOException e) {
throw new RuntimeException("Failed to get EQ code", e);
}
}
public static JSONObject stockByJYSFromHttp(String stockType, String symbol, String nseIndiaId) {
initCookie();
initCookie(NSE_INDIA_URL);
String url = NSE_INDIA_URL + "/api/quote-equity?symbol=" + nseIndiaId;
Request request = createRequest(url).newBuilder()
@@ -96,18 +126,44 @@ public class NseIndiaRequest {
}
}
public static StockHistoryResponse stockKLineFromHttp(StockHistoryRequest stockHistoryRequest) {
initCookie();
public static StockHistoryResponse stockKLineFromHttp(StockHistoryRequest stockHistoryRequest, String resolution) {
initCookie(NSE_INDIA_CHART_URL);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
String fromDate = sdf.format(new Date(stockHistoryRequest.getFrom() * 1000));
String toDate = sdf.format(new Date(stockHistoryRequest.getTo() * 1000));
Integer code = getCode(stockHistoryRequest.getSymbol());
String url = String.format("%s/api/historical/cm/equity?symbol=%s&from=%s&to=%s", NSE_INDIA_URL, stockHistoryRequest.getSymbol(), fromDate, toDate);
int interval = 1;
if (StringUtils.equals("H", resolution)) {
resolution = "I";
interval = 60;
}
Request request = createRequest(url).newBuilder()
.addHeader("referer", NSE_INDIA_URL)
.addHeader("origin", NSE_INDIA_URL)
Map<String, Object> body = new HashMap<>();
body.put("chartPeriod", resolution);
body.put("chartStart", 0);
body.put("exch", "N");
body.put("fromDate", 0);
body.put("instrType", "C");
body.put("scripCode", code);
body.put("timeInterval", interval);
body.put("toDate", stockHistoryRequest.getTo() + 18000);
body.put("ulToken", code);
String payload;
try {
payload = objectMapper.writeValueAsString(body);
} catch (Exception e) {
throw new RuntimeException("Failed to serialize body", e);
}
RequestBody requestBody = RequestBody.create(
MediaType.get("application/json; charset=utf-8"),
payload
);
Request request = createRequest(NSE_INDIA_CHART_URL + "//Charts/symbolhistoricaldata/").newBuilder()
.addHeader("referer", NSE_INDIA_CHART_URL)
.addHeader("origin", NSE_INDIA_CHART_URL)
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
@@ -115,52 +171,7 @@ public class NseIndiaRequest {
throw new IOException("Request failed with code: " + response.code());
}
JSONObject jsonData = JSONObject.parseObject(response.body().string());
JSONArray data =jsonData.getJSONArray("data");
StockHistoryResponse result = new StockHistoryResponse();
List<Long> tList = new ArrayList<>();
List<Double> oList = new ArrayList<>();
List<Double> hList = new ArrayList<>();
List<Double> lList = new ArrayList<>();
List<Double> cList = new ArrayList<>();
List<Long> vList = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
Long t, v;
Double o, h, l, c;
try {
JSONObject jsonObject = data.getJSONObject(i);
String timestampStr = jsonObject.getString("TIMESTAMP");
Instant instant = Instant.parse(timestampStr);
t = instant.toEpochMilli() / 1000;
o = jsonObject.getDouble("CH_OPENING_PRICE");
c = jsonObject.getDouble("CH_CLOSING_PRICE");
h = jsonObject.getDouble("CH_TRADE_HIGH_PRICE");
l = jsonObject.getDouble("CH_TRADE_LOW_PRICE");
v = jsonObject.getLong("CH_TOT_TRADED_VAL");
} catch (Exception e) {
continue;
}
tList.add(t);
oList.add(o);
hList.add(h);
lList.add(l);
cList.add(c);
vList.add(v);
}
result.setT(tList);
result.setO(oList);
result.setH(hList);
result.setL(lList);
result.setC(cList);
result.setV(vList);
StockHistoryResponse result = objectMapper.readValue(response.body().string(), StockHistoryResponse.class);
return result;
} catch (IOException e) {

View File

@@ -745,23 +745,21 @@ public class MoneyApiController {
// API request successful, return the response
return ResponseEntity.ok(response);
} else {
if (!StringUtils.equals("H", resolution)) {
try {
MoneyStock moneyStock = moneyStockRepository.findOne((QMoneyStockPO.moneyStockPO.moneyScId.eq(symbol))
.and(QMoneyStockPO.moneyStockPO.isLock.eq(0))
.and(QMoneyStockPO.moneyStockPO.isShow.eq(0)))
.orElse(null);
if (moneyStock != null && moneyStock.getNseIndiaId() != null && !moneyStock.getNseIndiaId().isEmpty()) {
request.setSymbol(moneyStock.getNseIndiaId());
response = NseIndiaRequest.stockKLineFromHttp(request);
if (moneyStock != null && moneyStock.getNseIndiaChartId() != null && !moneyStock.getNseIndiaChartId().isEmpty()) {
request.setSymbol(moneyStock.getNseIndiaChartId());
response = NseIndiaRequest.stockKLineFromHttp(request, resolution);
return ResponseEntity.ok(response);
}
} catch (Exception e) {
log.error("Failed to get data from nseindia.", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
}
// All retries failed, return an error response
log.error("Failed to get a successful response after {} retries.", maxRetries);