Compare commits

...

13 Commits

Author SHA1 Message Date
quangnguyen202
59e4aa9e1a Add alternal source 2024-09-19 14:33:22 +07:00
gavin
bae645e3c6 修复官方查询时名称写死的问题 2024-09-12 14:15:31 +08:00
gavin
94d9aea2c8 指定股票更换详情测试代码 2024-09-10 13:11:01 +08:00
gavin
5ae9762d45 指定股票更换详情测试代码 2024-09-09 14:59:38 +08:00
quangnguyen202
ece52491dd Merge branch 'refactor/optimization' into 'develop'
Optimize

See merge request india/india_market_java!38
2024-09-09 06:54:16 +00:00
quangnguyen202
6235d41711 Optimize 2024-09-06 11:17:41 +07:00
vpckiet
c865eccaf4 Merge branch 'refactor/optimization' into 'develop'
Optimize code

See merge request india/india_market_java!37
2024-09-06 01:53:33 +00:00
quangnguyen202
136020a497 Update 2024-09-05 16:30:46 +07:00
quangnguyen202
d7da59aca1 Optimize code 2024-09-05 15:59:13 +07:00
gavin
8427bed427 指定股票更换详情测试代码 2024-09-04 12:52:17 +08:00
gavin
269f02b79d 指定股票更换详情测试代码 2024-09-04 11:56:04 +08:00
gavin
7cc456bcd8 同步手动更新代码 2024-09-02 15:32:50 +08:00
vpckiet
be05d403af Merge branch 'bug/craw_img_news' into 'develop'
update crawl img news

See merge request india/india_market_java!33
2024-09-02 06:47:52 +00:00
4 changed files with 347 additions and 139 deletions

View File

@@ -56,6 +56,10 @@ public class MoneyStockPO {
* 展示表示 */
String selfDispId;
/**
* NSE India的id */
String nseIndiaId;
/**
* 自有self_url */
String selfUrl;

View File

@@ -0,0 +1,170 @@
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 okhttp3.*;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
public class NseIndiaRequest {
private static final String NSE_INDIA_URL = "https://www.nseindia.com";
private static final OkHttpClient client;
static {
client = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private final Map<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
})
.build();
}
private static Request createRequest(String url) {
Request request = new Request.Builder()
.url(url)
.header("accept", "application/json, text/plain, */*")
.header("accept-language", "en-US,en;q=0.9")
.header("cache-control", "no-cache")
.header("pragma", "no-cache")
.header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36")
.build();
return request;
}
private static void initCookie() {
Request request = createRequest(NSE_INDIA_URL);
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to fetch initial cookies");
}
} catch (IOException e) {
throw new RuntimeException("Failed to initialize cookies", e);
}
}
public static JSONObject stockByJYSFromHttp(String stockType, String symbol, String nseIndiaId) {
initCookie();
String url = NSE_INDIA_URL + "/api/quote-equity?symbol=" + nseIndiaId;
Request request = createRequest(url).newBuilder()
.addHeader("referer", NSE_INDIA_URL)
.addHeader("origin", NSE_INDIA_URL)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Request failed with code: " + response.code());
}
JSONObject jsonData = JSONObject.parseObject(response.body().string());
JSONObject data =jsonData.getJSONObject("priceInfo");
JSONObject json = new JSONObject();
json.put("pricepercentchange",data.getString("pChange"));
json.put("stockType",stockType);
json.put("pricechange",data.getString("change"));
json.put("pricecurrent",data.getString("lastPrice"));
json.put("priceprevclose",data.getString("previousClose"));
json.put("PREVDATE","");
json.put("VOL",jsonData.getJSONObject("preOpenMarket").getString("totalTradedVolume"));
json.put("dataSourceType","3");
json.put("symbol",symbol);
json.put("BSEID",symbol);
json.put("NSEID",symbol);
json.put("LTH",data.getString("upperCP"));
json.put("LTL",data.getString("lowerCP"));
json.put("OPN",data.getString("open"));
return json;
} catch (IOException e) {
throw new RuntimeException("Failed to fetch data", e);
}
}
public static StockHistoryResponse stockKLineFromHttp(StockHistoryRequest stockHistoryRequest) {
initCookie();
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));
String url = String.format("%s/api/historical/cm/equity?symbol=%s&from=%s&to=%s", NSE_INDIA_URL, stockHistoryRequest.getSymbol(), fromDate, toDate);
Request request = createRequest(url).newBuilder()
.addHeader("referer", NSE_INDIA_URL)
.addHeader("origin", NSE_INDIA_URL)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
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);
return result;
} catch (IOException e) {
throw new RuntimeException("Failed to fetch data", e);
}
}
}

View File

@@ -7,7 +7,7 @@ import cn.stock.market.domain.basic.repository.MoneyStockRepository;
import cn.stock.market.dto.StockHistoryRequest;
import cn.stock.market.dto.StockHistoryResponse;
import cn.stock.market.infrastructure.db.po.QMoneyStockPO;
import cn.stock.market.utils.RequestCacheUtils;
import cn.stock.market.utils.NseIndiaRequest;
import cn.stock.market.utils.ServerResponse;
import cn.stock.market.web.annotations.EncryptFilter;
import com.alibaba.fastjson.JSONObject;
@@ -39,10 +39,7 @@ import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -63,13 +60,11 @@ public class MoneyApiController {
private static final String EXTERNAL_API_URL = "https://priceapi.moneycontrol.com/techCharts/indianMarket/stock/history";
@ApiOperation(value = "股票详情信息",httpMethod = "GET")
@ApiOperation(value = "股票详情信息", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name="stockType",value = "BSE或者NSE"),
@ApiImplicitParam(name="symbol",value = "scId值"),
@ApiImplicitParam(name="id",value = "id值"),
@ApiImplicitParam(name = "stockType", value = "BSE或者NSE"),
@ApiImplicitParam(name = "symbol", value = "scId值"),
@ApiImplicitParam(name = "id", value = "id值"),
})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "" +
@@ -168,53 +163,67 @@ public class MoneyApiController {
"priceprevclose: 前一交易日的收盘价\n" +
"30DayAvg: 过去30天的平均", response = JSONObject.class),
})
@GetMapping({"/market/api/market/money/getStockDetail","/api/market/money/getStockDetail"})
@GetMapping({"/market/api/market/money/getStockDetail", "/api/market/money/getStockDetail"})
@ResponseBody
@EncryptFilter(decryptRequest = false)
public ServerResponse getStockDetail(@RequestParam String stockType, @RequestParam String symbol ) {
String url = String.format("https://priceapi.moneycontrol.com/pricefeed/%s/equitycash/%s",stockType,symbol);
public ServerResponse getStockDetail(@RequestParam String stockType, @RequestParam String symbol) {
MoneyStock moneyStock = moneyStockRepository.findOne(QMoneyStockPO.moneyStockPO.stockType.eq(stockType)
.and(QMoneyStockPO.moneyStockPO.moneyScId.eq(symbol))
.and(QMoneyStockPO.moneyStockPO.isLock.eq(0))
.and(QMoneyStockPO.moneyStockPO.isShow.eq(0)))
.and(QMoneyStockPO.moneyStockPO.moneyScId.eq(symbol))
.and(QMoneyStockPO.moneyStockPO.isLock.eq(0))
.and(QMoneyStockPO.moneyStockPO.isShow.eq(0)))
.orElse(null);
/* if(moneyStock==null){
return ServerResponse.createByErrorMsg("没有找到该股票");
}*/
// 设置重试次数
if ("ANI".equals(symbol)) {
JSONObject json1 = new JSONObject();
json1.put("company", "Archit Nuwood Industries Ltd");
json1.put("pricepercentchange", "Archit Nuwood Industries Ltd");
json1.put("stockType", stockType);
json1.put("pricecurrent", "386");
json1.put("dataSourceType", "3");
json1.put("symbol", "ANI");
json1.put("BSEID", "ANI");
json1.put("NSEID", "ANI");
return ServerResponse.createBySuccess(json1);
}
String url = String.format("https://priceapi.moneycontrol.com/pricefeed/%s/equitycash/%s", stockType, symbol);
int maxRetries = 3;
for (int retry = 1; retry <= maxRetries; retry++) {
try {
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
JSONObject json1 = new JSONObject();
if (responseEntity.getStatusCode().value() == 200 && responseEntity.getBody() != null ) {
if (responseEntity.getStatusCode().value() == 200 && responseEntity.getBody() != null) {
JSONObject data = JSONObject.parseObject(responseEntity.getBody()).getJSONObject("data");
if(data!=null){
json1.put("company",data.getString("SC_FULLNM"));
json1.put("pricepercentchange",data.getString("pricepercentchange"));
json1.put("stockType",stockType);
json1.put("pricechange",data.getString("pricechange"));
json1.put("pricecurrent",data.getString("pricecurrent"));
json1.put("priceprevclose",data.getString("priceprevclose"));
json1.put("PREVDATE",data.getString("PREVDATE"));
json1.put("VOL",data.getString("VOL"));
json1.put("dataSourceType","3");
json1.put("symbol",data.getString("symbol"));
json1.put("BSEID",data.getString("BSEID"));
json1.put("NSEID",data.getString("NSEID"));
json1.put("LTH",data.getString("HP"));
json1.put("LTL",data.getString("LP"));
json1.put("OPN",data.getString("OPN"));
if(null!=moneyStock){
json1.put("id",moneyStock.getId());
if (data != null) {
json1.put("company", data.getString("SC_FULLNM"));
json1.put("pricepercentchange", data.getString("pricepercentchange"));
json1.put("stockType", stockType);
json1.put("pricechange", data.getString("pricechange"));
json1.put("pricecurrent", data.getString("pricecurrent"));
json1.put("priceprevclose", data.getString("priceprevclose"));
json1.put("PREVDATE", data.getString("PREVDATE"));
json1.put("VOL", data.getString("VOL"));
json1.put("dataSourceType", "3");
json1.put("symbol", data.getString("symbol"));
json1.put("BSEID", data.getString("BSEID"));
json1.put("NSEID", data.getString("NSEID"));
json1.put("LTH", data.getString("HP"));
json1.put("LTL", data.getString("LP"));
json1.put("OPN", data.getString("OPN"));
if (null != moneyStock) {
json1.put("id", moneyStock.getId());
}
if(StringUtils.equals(data.getString("pricecurrent"),"0.00")
&& (!StringUtils.equals(data.getString("priceprevclose"),"0.00"))){
json1.put("pricecurrent",data.getString("priceprevclose"));
if (StringUtils.equals(data.getString("pricecurrent"), "0.00")
&& (!StringUtils.equals(data.getString("priceprevclose"), "0.00"))) {
json1.put("pricecurrent", data.getString("priceprevclose"));
}
}
return ServerResponse.createBySuccess(json1);
if (json1.size() > 0)
return ServerResponse.createBySuccess(json1);
}
} catch (Exception e) {
}
@@ -228,20 +237,31 @@ public class MoneyApiController {
}
}
}
if (moneyStock != null && moneyStock.getNseIndiaId() != null && !moneyStock.getNseIndiaId().isEmpty()) {
try {
// Get data from nseindia
JSONObject json = NseIndiaRequest.stockByJYSFromHttp(stockType, symbol, moneyStock.getNseIndiaId());
json.put("id", moneyStock.getId());
json.put("company",moneyStock.getStockName());
return ServerResponse.createBySuccess(json);
} catch (Exception e) {
return null;
}
}
return null;
}
private static List<MoneyStockSuggestDTO> nseActives() {
private static List<MoneyStockSuggestDTO> nseActives() {
List<MoneyStockSuggestDTO> list = new ArrayList<>();
String url = "https://www.moneycontrol.com/stocks/marketstats/nse-mostactive-stocks/nifty-50-9/";
try {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
for (int i =1;i<=size;i++){
for (int i = 1; i <= size; i++) {
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td.PR > span > a").first();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > a").first();
if (company_a != null) {
String stockUrl = company_a.attr("href");
String stockName = company_a.text();
@@ -249,7 +269,7 @@ public class MoneyApiController {
dto.setStockUrl(stockUrl);
}
String highPrice = getTextOrEmpty(doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td:nth-child(2)").first());
String highPrice = getTextOrEmpty(doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td:nth-child(2)").first());
dto.setHighPrice(highPrice);
String lowPrice = getTextOrEmpty(doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td:nth-child(3)").first());
@@ -274,7 +294,7 @@ public class MoneyApiController {
return list;
}
private static List<MoneyStockSuggestDTO> bseActives() {
private static List<MoneyStockSuggestDTO> bseActives() {
List<MoneyStockSuggestDTO> list = new ArrayList<>();
String url = "https://www.moneycontrol.com/stocks/marketstats/bsemact1/index.php";
@@ -282,9 +302,9 @@ public class MoneyApiController {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
System.err.println(size);
for (int i =1;i<=size;i++){
for (int i = 1; i <= size; i++) {
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td.PR > span > a").first();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > a").first();
if (company_a != null) {
String stockUrl = company_a.attr("href");
String stockName = company_a.text();
@@ -313,19 +333,19 @@ public class MoneyApiController {
}
} catch (IOException e) {
log.error("occur Exception",e);
log.error("occur Exception", e);
}
return list;
}
private static List<MoneyStockSuggestDTO> bseGainer() {
private static List<MoneyStockSuggestDTO> bseGainer() {
String url = "https://www.moneycontrol.com/stocks/marketstats/bse-gainer/sensex_4/";
List<MoneyStockSuggestDTO> list = Lists.newArrayList();
try {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
for (int i =1;i<=size;i++){
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td.PR > span > a").first();
for (int i = 1; i <= size; i++) {
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > a").first();
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
if (company_a != null) {
String stockUrl = company_a.attr("href");
@@ -369,9 +389,9 @@ public class MoneyApiController {
try {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
for (int i =1;i<=size;i++){
for (int i = 1; i <= size; i++) {
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td.PR > span > h3 > a").first();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > h3 > a").first();
if (company_a != null) {
String stockUrl = company_a.attr("href");
String stockName = company_a.text();
@@ -406,20 +426,20 @@ public class MoneyApiController {
return list;
}
private static List<MoneyStockSuggestDTO> nseTopLoser() {
private static List<MoneyStockSuggestDTO> nseTopLoser() {
String url = "https://www.moneycontrol.com/stocks/marketstats/nseloser/index.php";
List<MoneyStockSuggestDTO> list = Lists.newArrayList();
try {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
for (int i =1;i<=size;i++){
for (int i = 1; i <= size; i++) {
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child("+i+") > td.PR > span > h3 > a").first();
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > h3 > a").first();
if (company_a != null) {
String stockUrl = company_a.attr("href");
String stockName = company_a.text();
dto.setStockUrl(stockUrl);
dto.setStockUrl(stockUrl);
dto.setStockName(stockName);
}
@@ -446,7 +466,7 @@ public class MoneyApiController {
} catch (IOException e) {
e.printStackTrace();
}
return list;
return list;
}
private static List<MoneyStockSuggestDTO> bseTopLoser() {
@@ -456,7 +476,7 @@ public class MoneyApiController {
try {
Document doc = Jsoup.connect(url).get();
int size = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr").size();
for (int i =1;i<=size;i++){
for (int i = 1; i <= size; i++) {
Element company_a = doc.select("#mc_content > section > section > div.clearfix.stat_container > div.columnst.FR.wbg.brdwht > div > div > div.bsr_table.hist_tbl_hm > table > tbody > tr:nth-child(" + i + ") > td.PR > span > a").first();
MoneyStockSuggestDTO dto = new MoneyStockSuggestDTO();
if (company_a != null) {
@@ -501,17 +521,15 @@ public class MoneyApiController {
}
@ApiOperation(value = "股票推荐TopGainer",httpMethod = "GET")
@ApiOperation(value = "股票推荐TopGainer", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name="stockType",value = "BSE或者NSE"),
@ApiImplicitParam(name = "stockType", value = "BSE或者NSE"),
})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "" +
"股票推荐相关: top gainer", response = JSONObject.class),
})
@GetMapping({"/market/api/market/money/getTopGainer","/api/market/money/getTopGainer"})
@GetMapping({"/market/api/market/money/getTopGainer", "/api/market/money/getTopGainer"})
@ResponseBody
@EncryptFilter(decryptRequest = false)
@@ -529,15 +547,15 @@ public class MoneyApiController {
}
Map<Object, Boolean> map = new HashMap<>();
moneyStockSuggestDTOS = moneyStockSuggestDTOS.stream()
.filter(f->StringUtils.isNotBlank(f.getStockName()))
.filter(f -> StringUtils.isNotBlank(f.getStockName()))
.filter(i -> map.putIfAbsent(i.getStockName(), Boolean.TRUE) == null).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)){
if (CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)) {
List<String> selfUlrList = moneyStockSuggestDTOS.stream().map(MoneyStockSuggestDTO::getStockName).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(selfUlrList)){
if (CollectionUtils.isNotEmpty(selfUlrList)) {
List<MoneyStock> all = moneyStockRepository.findAll(QMoneyStockPO.moneyStockPO.stockName.in(selfUlrList));
if(CollectionUtils.isNotEmpty(all)){
moneyStockSuggestDTOS.stream().filter(f->all.stream().anyMatch(s->s.getStockName().equals(f.getStockName())))
.forEach(f->f.setScId(all.stream().filter(s->s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
if (CollectionUtils.isNotEmpty(all)) {
moneyStockSuggestDTOS.stream().filter(f -> all.stream().anyMatch(s -> s.getStockName().equals(f.getStockName())))
.forEach(f -> f.setScId(all.stream().filter(s -> s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
}
}
gainerStockSuggestCache.put(stockType, moneyStockSuggestDTOS);
@@ -548,47 +566,47 @@ public class MoneyApiController {
}
@ApiOperation(value = "股票推荐TopLoser",httpMethod = "GET")
@ApiOperation(value = "股票推荐TopLoser", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name="stockType",value = "BSE或者NSE"),
@ApiImplicitParam(name = "stockType", value = "BSE或者NSE"),
})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "" +
"股票推荐相关: TopLoser", response = JSONObject.class),
})
@GetMapping({"/market/api/market/money/getTopLoser","/api/market/money/getTopLoser"})
@GetMapping({"/market/api/market/money/getTopLoser", "/api/market/money/getTopLoser"})
@ResponseBody
@EncryptFilter(decryptRequest = false)
public List<MoneyStockSuggestDTO> getTopLoser(@RequestParam String stockType) {
List<MoneyStockSuggestDTO> moneyStockSuggestDTOS = null;
moneyStockSuggestDTOS = loserStockSuggestCache.getIfPresent(stockType);
if(null==moneyStockSuggestDTOS){
if(StringUtils.equals(stockType,"nse")){
if (null == moneyStockSuggestDTOS) {
if (StringUtils.equals(stockType, "nse")) {
moneyStockSuggestDTOS = nseTopLoser();
}else if(StringUtils.equals(stockType,"bse")){
} else if (StringUtils.equals(stockType, "bse")) {
moneyStockSuggestDTOS = bseTopLoser();
}
Map<Object, Boolean> map = new HashMap<>();
moneyStockSuggestDTOS = moneyStockSuggestDTOS.stream()
.filter(f->StringUtils.isNotBlank(f.getStockName()))
.filter(f -> StringUtils.isNotBlank(f.getStockName()))
.filter(i -> map.putIfAbsent(i.getStockName(), Boolean.TRUE) == null).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)){
moneyStockSuggestDTOS.stream().forEach(f->f.setDispId(extractLastSegment(f.getStockUrl())));
if (CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)) {
moneyStockSuggestDTOS.stream().forEach(f -> f.setDispId(extractLastSegment(f.getStockUrl())));
List<String> selfUlrList = moneyStockSuggestDTOS.stream().map(MoneyStockSuggestDTO::getStockName).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(selfUlrList)){
if (CollectionUtils.isNotEmpty(selfUlrList)) {
List<MoneyStock> all = moneyStockRepository.findAll(QMoneyStockPO.moneyStockPO.stockName.in(selfUlrList));
if(CollectionUtils.isNotEmpty(all)){
moneyStockSuggestDTOS.stream().filter(f->all.stream().anyMatch(s->s.getStockName().equals(f.getStockName())))
.forEach(f->f.setScId(all.stream().filter(s->s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
if (CollectionUtils.isNotEmpty(all)) {
moneyStockSuggestDTOS.stream().filter(f -> all.stream().anyMatch(s -> s.getStockName().equals(f.getStockName())))
.forEach(f -> f.setScId(all.stream().filter(s -> s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
}
List<MoneyStockSuggestDTO> noScIdList = moneyStockSuggestDTOS.stream().filter(f->StringUtils.isBlank(f.getScId())).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(noScIdList)){
List<MoneyStockSuggestDTO> noScIdList = moneyStockSuggestDTOS.stream().filter(f -> StringUtils.isBlank(f.getScId())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(noScIdList)) {
List<String> dispIdList = noScIdList.stream().map(MoneyStockSuggestDTO::getDispId).collect(Collectors.toList());
List<MoneyStock> all1 = moneyStockRepository.findAll(QMoneyStockPO.moneyStockPO.selfDispId.in(dispIdList));
if(CollectionUtils.isNotEmpty(all1)){
moneyStockSuggestDTOS.stream().filter(f->all1.stream().anyMatch(s->s.getSelfDispId().equals(f.getDispId())))
.forEach(f->f.setScId(all.stream().filter(s->s.getSelfDispId().equals(f.getDispId())).findFirst().orElse(null).getMoneyScId()));
if (CollectionUtils.isNotEmpty(all1)) {
moneyStockSuggestDTOS.stream().filter(f -> all1.stream().anyMatch(s -> s.getSelfDispId().equals(f.getDispId())))
.forEach(f -> f.setScId(all.stream().filter(s -> s.getSelfDispId().equals(f.getDispId())).findFirst().orElse(null).getMoneyScId()));
}
}
}
@@ -599,49 +617,47 @@ public class MoneyApiController {
}
@ApiOperation(value = "股票推荐TopActive",httpMethod = "GET")
@ApiOperation(value = "股票推荐TopActive", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name="stockType",value = "BSE或者NSE"),
@ApiImplicitParam(name = "stockType", value = "BSE或者NSE"),
})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "" +
"股票推荐相关: top active", response = JSONObject.class),
})
@GetMapping({"/market/api/market/money/getTopActives","/api/market/money/getTopActives"})
@GetMapping({"/market/api/market/money/getTopActives", "/api/market/money/getTopActives"})
@ResponseBody
@EncryptFilter(decryptRequest = false)
public List<MoneyStockSuggestDTO> getTopActive(@RequestParam String stockType) {
List<MoneyStockSuggestDTO> moneyStockSuggestDTOS = null;
moneyStockSuggestDTOS = activesStockSuggestCache.getIfPresent(stockType);
if(moneyStockSuggestDTOS ==null){
if(StringUtils.equals(stockType,"nse")){
if (moneyStockSuggestDTOS == null) {
if (StringUtils.equals(stockType, "nse")) {
moneyStockSuggestDTOS = nseActives();
}else if(StringUtils.equals(stockType,"bse")){
} else if (StringUtils.equals(stockType, "bse")) {
moneyStockSuggestDTOS = bseActives();
}
Map<Object, Boolean> map = new HashMap<>();
moneyStockSuggestDTOS = moneyStockSuggestDTOS.stream()
.filter(f->StringUtils.isNotBlank(f.getStockName()))
.filter(f -> StringUtils.isNotBlank(f.getStockName()))
.filter(i -> map.putIfAbsent(i.getStockName(), Boolean.TRUE) == null).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)){
moneyStockSuggestDTOS.stream().forEach(f->f.setDispId(extractLastSegment(f.getStockUrl())));
if (CollectionUtils.isNotEmpty(moneyStockSuggestDTOS)) {
moneyStockSuggestDTOS.stream().forEach(f -> f.setDispId(extractLastSegment(f.getStockUrl())));
List<String> selfUlrList = moneyStockSuggestDTOS.stream().map(MoneyStockSuggestDTO::getStockName).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(selfUlrList)){
if (CollectionUtils.isNotEmpty(selfUlrList)) {
List<MoneyStock> all = moneyStockRepository.findAll(QMoneyStockPO.moneyStockPO.stockName.in(selfUlrList));
if(CollectionUtils.isNotEmpty(all)){
moneyStockSuggestDTOS.stream().filter(f->all.stream().anyMatch(s->s.getStockName().equals(f.getStockName())))
.forEach(f->f.setScId(all.stream().filter(s->s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
if (CollectionUtils.isNotEmpty(all)) {
moneyStockSuggestDTOS.stream().filter(f -> all.stream().anyMatch(s -> s.getStockName().equals(f.getStockName())))
.forEach(f -> f.setScId(all.stream().filter(s -> s.getStockName().equals(f.getStockName())).findFirst().orElse(null).getMoneyScId()));
}
List<MoneyStockSuggestDTO> noScIdList = moneyStockSuggestDTOS.stream().filter(f->StringUtils.isBlank(f.getScId())).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(noScIdList)){
List<MoneyStockSuggestDTO> noScIdList = moneyStockSuggestDTOS.stream().filter(f -> StringUtils.isBlank(f.getScId())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(noScIdList)) {
List<String> dispIdList = noScIdList.stream().map(MoneyStockSuggestDTO::getDispId).collect(Collectors.toList());
List<MoneyStock> all1 = moneyStockRepository.findAll(QMoneyStockPO.moneyStockPO.selfDispId.in(dispIdList));
if(CollectionUtils.isNotEmpty(all1)){
moneyStockSuggestDTOS.stream().filter(f->all1.stream().anyMatch(s->s.getSelfDispId().equals(f.getDispId())))
.forEach(f->f.setScId(all.stream().filter(s->s.getSelfDispId().equals(f.getDispId())).findFirst().orElse(null).getMoneyScId()));
if (CollectionUtils.isNotEmpty(all1)) {
moneyStockSuggestDTOS.stream().filter(f -> all1.stream().anyMatch(s -> s.getSelfDispId().equals(f.getDispId())))
.forEach(f -> f.setScId(all.stream().filter(s -> s.getSelfDispId().equals(f.getDispId())).findFirst().orElse(null).getMoneyScId()));
}
}
}
@@ -653,9 +669,8 @@ public class MoneyApiController {
}
@GetMapping({"/market/api/market/money/history/kLine","/api/market/money/history/kLine"})
@ApiOperation(value = "获取kline的money数据源", notes = "获取kline的money数据源",response = StockHistoryResponse.class)
@GetMapping({"/market/api/market/money/history/kLine", "/api/market/money/history/kLine"})
@ApiOperation(value = "获取kline的money数据源", notes = "获取kline的money数据源", response = StockHistoryResponse.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "symbol", value = "Stock symbol 对应的是NSEID 或者是BSEID", required = true, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "resolution", value = "单位:60 1D 1W 1D 对应H,D,W,Y", required = true, dataType = "String", paramType = "query"),
@@ -665,34 +680,34 @@ public class MoneyApiController {
@ApiImplicitParam(name = "currencyCode", value = "INR 不变", required = true, dataType = "String", paramType = "query")
})
@ResponseBody
@EncryptFilter(decryptRequest = false)
public ResponseEntity<StockHistoryResponse> getStockHistory( @RequestParam String symbol,
@RequestParam String resolution
) {
@EncryptFilter(decryptRequest = false)
public ResponseEntity<StockHistoryResponse> getStockHistory(@RequestParam String symbol,
@RequestParam String resolution
) {
// 向外部API发起请求并获取响应
StockHistoryRequest request = new StockHistoryRequest();
request.setSymbol(symbol);
Long to = null;
Long from = null;
int countback = 5;
if(StringUtils.equals("H",resolution)){
to = (long) (System.currentTimeMillis() / 1000);
from = to - ( 60 * 60 );
if (StringUtils.equals("H", resolution)) {
to = (long) (System.currentTimeMillis() / 1000);
from = to - (60 * 60);
countback = 60;
request.setResolution("1");
}else if(StringUtils.equals("D",resolution)){
to = (long) (System.currentTimeMillis() / 1000);
from = to - (24 * 60 * 60 );
} else if (StringUtils.equals("D", resolution)) {
to = (long) (System.currentTimeMillis() / 1000);
from = to - (24 * 60 * 60);
countback = 390;
request.setResolution("1");
}else if(StringUtils.equals("W",resolution)){
to = (long) (System.currentTimeMillis() / 1000);
from = to - (7 * 24 * 60 * 60 );
} else if (StringUtils.equals("W", resolution)) {
to = (long) (System.currentTimeMillis() / 1000);
from = to - (7 * 24 * 60 * 60);
countback = 471;
request.setResolution("5");
}else if(StringUtils.equals("M",resolution)){
to = (long) (System.currentTimeMillis() / 1000);
from = to - (35 * 24 * 60 * 60 );
} else if (StringUtils.equals("M", resolution)) {
to = (long) (System.currentTimeMillis() / 1000);
from = to - (35 * 24 * 60 * 60);
countback = 328;
request.setResolution("30");
}
@@ -702,7 +717,7 @@ public class MoneyApiController {
request.setCountback(countback);
request.setCurrencyCode("INR");
String apiUrl = buildApiUrl(request);
log.info("request url:"+apiUrl);
log.info("request url:" + apiUrl);
StockHistoryResponse response = null;
int maxRetries = 3;
int retryCount = 0;
@@ -726,10 +741,28 @@ public class MoneyApiController {
}
if (response != null) {
setResponse(response,resolution);
setResponse(response, resolution);
// 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);
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);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
@@ -737,14 +770,14 @@ public class MoneyApiController {
// 返回响应
}
private void setResponse(StockHistoryResponse response,String resolution){
if(!"ok".equals(response.getS())){
private void setResponse(StockHistoryResponse response, String resolution) {
if (!"ok".equals(response.getS())) {
return;
}
if(Objects.isNull(response.getT())){
if (Objects.isNull(response.getT())) {
return;
}
if(StringUtils.equals("H",resolution) || StringUtils.equals("D",resolution)) {
if (StringUtils.equals("H", resolution) || StringUtils.equals("D", resolution)) {
List<Long> t = new ArrayList<>();
List<Double> o = new ArrayList<>();
List<Double> h = new ArrayList<>();
@@ -756,7 +789,7 @@ public class MoneyApiController {
Date currentTime = new Date();
//判断最后一条是不是当天的数据,如果不是,把最后一条的时间作为当天的时间
long getTime = response.getT().get(response.getT().size() - 1) * 1000L;
if(!DateUtil.isSameDay(currentTime, new Date(getTime))){
if (!DateUtil.isSameDay(currentTime, new Date(getTime))) {
currentTime = new Date(getTime);
}
int i = 0;
@@ -782,14 +815,14 @@ public class MoneyApiController {
}
private String buildApiUrl(StockHistoryRequest request) {
// 构建外部API的URL
return String.format("%s?symbol=%s&resolution=%s&from=%d&to=%d&countback=%d&currencyCode=%s",
EXTERNAL_API_URL, request.getSymbol(), request.getResolution(), request.getFrom(),
request.getTo(), request.getCountback(), request.getCurrencyCode());
};
}
;
private static String extractLastSegment(String url) {
@@ -814,7 +847,7 @@ public class MoneyApiController {
//// bseTopLoser();
System.out.println(new Date());
System.out.println(new Date(1713949200000L));
System.out.println(DateUtil.isSameDay(new Date(),new Date(1713949200000L)));
System.out.println(DateUtil.isSameDay(new Date(), new Date(1713949200000L)));
}
private Cache<String, List<MoneyStockSuggestDTO>> gainerStockSuggestCache = CacheBuilder.newBuilder()

View File

@@ -14,6 +14,7 @@ import cn.qutaojing.common.jpa.ConditionBuilder;
import cn.stock.market.domain.basic.entity.SiteNews;
import cn.stock.market.domain.basic.repository.SiteNewsRepository;
import cn.stock.market.infrastructure.db.po.QSiteNewsPO;
import cn.stock.market.infrastructure.job.InvestingTask;
import cn.stock.market.web.annotations.EncryptFilter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -178,7 +179,7 @@ public class StockApiController {
newsList.forEach( n -> {
String contentUrl = n.substring(1, n.indexOf("class=\"img-smllnews\"") - 2);
String id = contentUrl.substring(contentUrl.lastIndexOf("-") + 1, contentUrl.lastIndexOf("_"));
String imgUrl = n.substring(n.indexOf("img loading=\"lazy\" src=") + 24, n.indexOf("?"));
String imgUrl = InvestingTask.extractImgSrc(n);
// String time = n.substring(n.indexOf("Last Updated") + 23, n.indexOf("IST") - 9);
// Extract the date and time using regex
Pattern pattern = Pattern.compile("Updated On :<!-- --> <!-- -->(.*?)<!-- -->");