use of com.mistra.plank.pojo.entity.DailyRecord in project plank by MistraR.
the class Barbarossa method sellStock.
/**
* 减仓或清仓股票
*
* @param date 日期
*/
private void sellStock(Date date) {
List<HoldShares> holdShares = holdSharesMapper.selectList(new QueryWrapper<>());
if (CollectionUtils.isNotEmpty(holdShares)) {
for (HoldShares holdShare : holdShares) {
if (!DateUtils.isSameDay(holdShare.getBuyTime(), date) && holdShare.getBuyTime().getTime() < date.getTime()) {
Page<DailyRecord> selectPage = dailyRecordMapper.selectPage(new Page<>(1, 25), new QueryWrapper<DailyRecord>().eq("code", holdShare.getCode()).ge("date", DateUtils.addDays(date, -plankConfig.getDeficitMovingAverage() - 9)).le("date", date).orderByDesc("date"));
// 今日数据明细
DailyRecord todayRecord = selectPage.getRecords().get(0);
List<DailyRecord> dailyRecords = selectPage.getRecords().size() >= plankConfig.getDeficitMovingAverage() ? selectPage.getRecords().subList(0, plankConfig.getDeficitMovingAverage() - 1) : selectPage.getRecords();
// 止损均线价格
OptionalDouble average = dailyRecords.stream().mapToDouble(dailyRecord -> dailyRecord.getClosePrice().doubleValue()).average();
if (average.isPresent() && (todayRecord.getLowest().doubleValue() <= average.getAsDouble())) {
// 跌破均线,清仓
this.clearanceStock(holdShare, ClearanceReasonEnum.BREAK_POSITION, date, average.getAsDouble());
continue;
}
// 盘中最低收益率
double profitLowRatio = todayRecord.getLowest().subtract(holdShare.getBuyPrice()).divide(holdShare.getBuyPrice(), 2, RoundingMode.HALF_UP).doubleValue();
if (profitLowRatio < plankConfig.getDeficitRatio().doubleValue()) {
// 跌破止损线,清仓
this.clearanceStock(holdShare, ClearanceReasonEnum.BREAK_LOSS_LINE, date, holdShare.getBuyPrice().doubleValue() * (1 + plankConfig.getDeficitRatio().doubleValue()));
continue;
}
if (holdShare.getFifteenProfit() && profitLowRatio <= plankConfig.getProfitClearanceRatio().doubleValue()) {
// 收益回撤到10个点止盈清仓
this.clearanceStock(holdShare, ClearanceReasonEnum.TAKE_PROFIT, date, holdShare.getBuyPrice().doubleValue() * 1.1);
continue;
}
// 盘中最高收益率
double profitHighRatio = todayRecord.getHighest().subtract(holdShare.getBuyPrice()).divide(holdShare.getBuyPrice(), 2, RoundingMode.HALF_UP).doubleValue();
if (profitHighRatio >= plankConfig.getProfitUpperRatio().doubleValue()) {
// 收益25% 清仓
this.clearanceStock(holdShare, ClearanceReasonEnum.PROFIT_UPPER, date, holdShare.getBuyPrice().doubleValue() * (1 + plankConfig.getProfitUpperRatio().doubleValue()));
} else if (profitHighRatio >= plankConfig.getProfitQuarterRatio().doubleValue()) {
// 收益20% 减至1/4仓
this.reduceStock(holdShare, ClearanceReasonEnum.POSITION_QUARTER, date, todayRecord, holdShare.getBuyPrice().doubleValue() * (1 + plankConfig.getProfitQuarterRatio().doubleValue()));
} else if (profitHighRatio >= plankConfig.getProfitHalfRatio().doubleValue()) {
// 收益15% 减半仓
this.reduceStock(holdShare, ClearanceReasonEnum.POSITION_HALF, date, todayRecord, holdShare.getBuyPrice().doubleValue() * (1 + plankConfig.getProfitHalfRatio().doubleValue()));
}
// 持股超过x天 并且 收益不到20% 清仓
if (Days.daysBetween(new LocalDate(holdShare.getBuyTime().getTime()), new LocalDate(date.getTime())).getDays() > plankConfig.getClearanceDay()) {
this.clearanceStock(holdShare, ClearanceReasonEnum.TEN_DAY, date, todayRecord.getOpenPrice().add(todayRecord.getClosePrice()).doubleValue() / 2);
}
}
}
}
}
use of com.mistra.plank.pojo.entity.DailyRecord in project plank by MistraR.
the class Barbarossa method analyze.
/**
* 分析最近一个月各连板晋级率
*/
public void analyze() {
// 4连板+的股票
HashSet<String> fourPlankStock = new HashSet<>();
HashMap<String, Integer> gemPlankStockNumber = new HashMap<>();
Date date = new DateTime(DateUtils.addDays(new Date(), -30)).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0).toDate();
// 首板一进二胜率
HashMap<String, BigDecimal> oneToTwo = new HashMap<>(64);
// 二板二进三胜率
HashMap<String, BigDecimal> twoToThree = new HashMap<>(64);
// 三板三进四胜率
HashMap<String, BigDecimal> threeToFour = new HashMap<>(64);
// 四板四进五胜率
HashMap<String, BigDecimal> fourToFive = new HashMap<>(64);
// 五板五进六胜率
HashMap<String, BigDecimal> fiveToSix = new HashMap<>(64);
// 六板六进七胜率
HashMap<String, BigDecimal> sixToSeven = new HashMap<>(64);
List<DailyRecord> dailyRecords = dailyRecordMapper.selectList(new QueryWrapper<DailyRecord>().ge("date", date));
Map<String, List<DailyRecord>> dateListMap = dailyRecords.stream().collect(Collectors.groupingBy(dailyRecord -> sdf.format(dailyRecord.getDate())));
// 昨日首板
HashMap<String, Double> yesterdayOne = new HashMap<>(64);
// 昨日二板
HashMap<String, Double> yesterdayTwo = new HashMap<>(64);
// 昨日三板
HashMap<String, Double> yesterdayThree = new HashMap<>(64);
// 昨日四板
HashMap<String, Double> yesterdayFour = new HashMap<>(64);
// 昨日五板
HashMap<String, Double> yesterdayFive = new HashMap<>(64);
// 昨日六板
HashMap<String, Double> yesterdaySix = new HashMap<>(64);
do {
List<DailyRecord> records = dateListMap.get(sdf.format(date));
if (CollectionUtils.isNotEmpty(records)) {
// 今日首板
HashMap<String, Double> todayOne = new HashMap<>(64);
// 今日二板
HashMap<String, Double> todayTwo = new HashMap<>(32);
// 今日三板
HashMap<String, Double> todayThree = new HashMap<>(16);
// 今日四板
HashMap<String, Double> todayFour = new HashMap<>(16);
// 今日五板
HashMap<String, Double> todayFive = new HashMap<>(16);
// 今日六板
HashMap<String, Double> todaySix = new HashMap<>(16);
// 今日七板
HashMap<String, Double> todaySeven = new HashMap<>(16);
for (DailyRecord dailyRecord : records) {
double v = dailyRecord.getIncreaseRate().doubleValue();
String name = dailyRecord.getName();
String code = dailyRecord.getCode();
if (code.contains("SZ30") && v > 19.4 && v < 21) {
gemPlankStockNumber.put(name, gemPlankStockNumber.getOrDefault(name, 0) + 1);
}
if ((!code.contains("SZ30") && v > 9.4 && v < 11) || (code.contains("SZ30") && v > 19.4 && v < 21)) {
if (yesterdaySix.containsKey(name)) {
// 昨日的六板,今天继续板,进阶7板
todaySeven.put(dailyRecord.getName(), v);
} else if (yesterdayFive.containsKey(name)) {
// 昨日的五板,今天继续板,进阶6板
todaySix.put(dailyRecord.getName(), v);
} else if (yesterdayFour.containsKey(name)) {
// 昨日的四板,今天继续板,进阶5板
todayFive.put(dailyRecord.getName(), v);
} else if (yesterdayThree.containsKey(name)) {
// 昨日的三板,今天继续板,进阶4板
todayFour.put(dailyRecord.getName(), v);
} else if (yesterdayTwo.containsKey(name)) {
// 昨日的二板,今天继续板,进阶3板
todayThree.put(dailyRecord.getName(), v);
} else if (yesterdayOne.containsKey(name)) {
// 昨日首板,今天继续板,进阶2板
todayTwo.put(dailyRecord.getName(), v);
} else if (!yesterdayOne.containsKey(name)) {
// 昨日没有板,今日首板
todayOne.put(dailyRecord.getName(), v);
}
}
}
this.promotion(oneToTwo, todayTwo, yesterdayOne, date);
this.promotion(twoToThree, todayThree, yesterdayTwo, date);
this.promotion(threeToFour, todayFour, yesterdayThree, date);
this.promotion(fourToFive, todayFive, yesterdayFour, date);
this.promotion(fiveToSix, todaySix, yesterdayFive, date);
this.promotion(sixToSeven, todaySeven, yesterdaySix, date);
log.info("\n-------------------------------------------------------------------------------------------{}日-------------------------------------------------------------------------------------------" + "\n一板{}支:{}\n二板{}支:{}\n三板{}支:{}\n四板{}支:{}\n五板{}支:{}\n六板{}支:{}\n七板{}支:{}" + "\n--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------", sdf.format(date), todayOne.keySet().size(), new ArrayList<>(todayOne.keySet()), todayTwo.keySet().size(), new ArrayList<>(todayTwo.keySet()), todayThree.keySet().size(), new ArrayList<>(todayThree.keySet()), todayFour.keySet().size(), new ArrayList<>(todayFour.keySet()), todayFive.keySet().size(), new ArrayList<>(todayFive.keySet()), todaySix.keySet().size(), new ArrayList<>(todaySix.keySet()), todaySeven.keySet().size(), new ArrayList<>(todaySeven.keySet()));
fourPlankStock.addAll(todayFour.keySet());
yesterdayOne.clear();
yesterdayOne.putAll(todayOne);
yesterdayTwo.clear();
yesterdayTwo.putAll(todayTwo);
yesterdayThree.clear();
yesterdayThree.putAll(todayThree);
yesterdayFour.clear();
yesterdayFour.putAll(todayFour);
yesterdayFive.clear();
yesterdayFive.putAll(todayFive);
yesterdaySix.clear();
yesterdaySix.putAll(todaySix);
}
date = DateUtils.addDays(date, 1);
} while (date.getTime() < System.currentTimeMillis());
List<String> gemPlankStockTwice = new ArrayList<>();
for (Map.Entry<String, Integer> entry : gemPlankStockNumber.entrySet()) {
if (entry.getValue() > 1) {
gemPlankStockTwice.add(entry.getKey());
}
}
log.info("最近一个月4连板+的股票:{}", fourPlankStock.toString().replace(" ", "").replace("[", "").replace("]", ""));
log.info("最近一个月创业板涨停2次+的股票:{}", gemPlankStockTwice.toString().replace(" ", "").replace("[", "").replace("]", ""));
log.info("一板>一进二平均胜率:{}", (double) Math.round(oneToTwo.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
log.info("二板>二进三平均胜率:{}", (double) Math.round(twoToThree.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
log.info("三板>三进四平均胜率:{}", (double) Math.round(threeToFour.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
log.info("四板>四进五平均胜率:{}", (double) Math.round(fourToFive.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
log.info("五板>五进六平均胜率:{}", (double) Math.round(fiveToSix.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
log.info("六板>六进七平均胜率:{}", (double) Math.round(sixToSeven.values().stream().collect(Collectors.averagingDouble(BigDecimal::doubleValue)) * 100) / 100);
}
use of com.mistra.plank.pojo.entity.DailyRecord in project plank by MistraR.
the class Barbarossa method fundHoldingsImport.
public void fundHoldingsImport(FundHoldingsParam fundHoldingsParam, Date beginTime, Date endTime) {
UploadDataListener<ForeignFundHoldingsTracking> uploadDataListener = new UploadDataListener<>(500);
try {
EasyExcel.read(fundHoldingsParam.getFile().getInputStream(), ForeignFundHoldingsTracking.class, uploadDataListener).sheet().headRowNumber(2).doRead();
} catch (IOException e) {
log.error("read excel file error,file name:{}", fundHoldingsParam.getFile().getName());
}
for (Map.Entry<Integer, ForeignFundHoldingsTracking> entry : uploadDataListener.getMap().entrySet()) {
executorService.submit(() -> {
ForeignFundHoldingsTracking fundHoldingsTracking = entry.getValue();
try {
Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("name", fundHoldingsTracking.getName()));
fundHoldingsTracking.setCode(stock.getCode());
fundHoldingsTracking.setQuarter(fundHoldingsParam.getQuarter());
List<DailyRecord> dailyRecordList = dailyRecordMapper.selectList(new QueryWrapper<DailyRecord>().eq("name", fundHoldingsTracking.getName()).ge("date", beginTime).le("date", endTime));
if (CollectionUtils.isEmpty(dailyRecordList)) {
HashMap<String, String> stockMap = new HashMap<>();
stockMap.put(stock.getCode(), stock.getName());
dailyRecordProcessor.run(stockMap);
Thread.sleep(60 * 1000);
dailyRecordList = dailyRecordMapper.selectList(new QueryWrapper<DailyRecord>().eq("name", fundHoldingsTracking.getName()).ge("date", beginTime).le("date", endTime));
}
double average = dailyRecordList.stream().map(DailyRecord::getClosePrice).mapToInt(BigDecimal::intValue).average().orElse(0D);
fundHoldingsTracking.setAveragePrice(new BigDecimal(average));
fundHoldingsTracking.setShareholdingChangeAmount(average * fundHoldingsTracking.getShareholdingChangeCount());
fundHoldingsTracking.setModifyTime(new Date());
fundHoldingsTracking.setForeignTotalMarketDynamic(0L);
fundHoldingsTracking.setForeignFundTotalMarketDynamic(0L);
fundHoldingsTrackingMapper.insert(fundHoldingsTracking);
log.warn("更新[ {} ]{}季报基金持仓数据完成!", stock.getName(), fundHoldingsParam.getQuarter());
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
use of com.mistra.plank.pojo.entity.DailyRecord in project plank by MistraR.
the class Barbarossa method checkCanBuyStock.
/**
* 检查可以买的票 首板或者2板 10日涨幅介于10-22% 计算前8天的振幅在15%以内
*
* @return List<String>
*/
private List<Stock> checkCanBuyStock(Date date) {
List<DragonList> dragonLists = dragonListMapper.selectList(new QueryWrapper<DragonList>().ge("date", date).lt("date", DateUtils.addDays(date, 1)).ge("price", 5).le("price", 100).notLike("name", "%ST%").notLike("name", "%st%").notLike("name", "%A%").notLike("name", "%C%").notLike("name", "%N%").notLike("name", "%U%").notLike("name", "%W%").notLike("code", "%BJ%").notLike("code", "%688%"));
if (CollectionUtils.isEmpty(dragonLists)) {
return null;
}
List<DailyRecord> dailyRecords = new ArrayList<>();
for (DragonList dragonList : dragonLists) {
Page<DailyRecord> page = dailyRecordMapper.selectPage(new Page<>(1, 30), new QueryWrapper<DailyRecord>().eq("code", dragonList.getCode()).le("date", date).ge("date", DateUtils.addDays(date, -30)).orderByDesc("date"));
if (page.getRecords().size() > 10) {
dailyRecords.addAll(page.getRecords().subList(0, 10));
}
}
Map<String, List<DailyRecord>> map = dailyRecords.stream().collect(Collectors.groupingBy(DailyRecord::getCode));
List<String> stockCode = new ArrayList<>();
for (Map.Entry<String, List<DailyRecord>> entry : map.entrySet()) {
// 近8日涨幅
BigDecimal eightRatio = entry.getValue().get(0).getClosePrice().divide(entry.getValue().get(8).getClosePrice(), 2, RoundingMode.HALF_UP);
// 近3日涨幅
BigDecimal threeRatio = entry.getValue().get(0).getClosePrice().divide(entry.getValue().get(3).getClosePrice(), 2, RoundingMode.HALF_UP);
// 前3个交易日大跌的也排除
if (eightRatio.doubleValue() <= 1.22 && eightRatio.doubleValue() >= 1.1 && threeRatio.doubleValue() < 1.22 && entry.getValue().get(0).getIncreaseRate().doubleValue() > 0.04 && entry.getValue().get(1).getIncreaseRate().doubleValue() > -0.04 && entry.getValue().get(2).getIncreaseRate().doubleValue() > -0.04) {
stockCode.add(entry.getKey());
}
}
dragonLists = dragonLists.stream().filter(dragonList -> stockCode.contains(dragonList.getCode())).collect(Collectors.toList());
dragonLists = dragonLists.stream().sorted((a, b) -> b.getNetBuy().compareTo(a.getNetBuy())).collect(Collectors.toList());
List<Stock> result = new ArrayList<>();
for (DragonList dragonList : dragonLists) {
result.add(stockMapper.selectOne(new QueryWrapper<Stock>().eq("code", dragonList.getCode())));
}
return result;
}
use of com.mistra.plank.pojo.entity.DailyRecord in project plank by MistraR.
the class DailyRecordProcessor method run.
public void run(HashMap<String, String> map) {
Integer count = dailyRecordMapper.selectCount(new QueryWrapper<DailyRecord>().ge("date", DateUtils.addDays(new Date(), -1)));
if (count > 0) {
log.info("今日已经更新过交易数据,一共:{}条!", count);
return;
}
log.info("开始更新股票每日成交数据!");
for (Map.Entry<String, String> entry : map.entrySet()) {
executorService.submit(() -> {
try {
String url = plankConfig.getXueQiuStockDetailUrl().replace("{code}", entry.getKey()).replace("{time}", String.valueOf(System.currentTimeMillis())).replace("{recentDayNumber}", String.valueOf(plankConfig.getRecentDayNumber()));
String body = HttpUtil.getHttpGetResponseString(url, plankConfig.getXueQiuCookie());
JSONObject data = JSON.parseObject(body).getJSONObject("data");
JSONArray list = data.getJSONArray("item");
if (CollectionUtils.isNotEmpty(list)) {
JSONArray array;
for (Object o : list) {
array = (JSONArray) o;
DailyRecord dailyRecord = new DailyRecord();
dailyRecord.setDate(new Date(array.getLongValue(0)));
dailyRecord.setCode(entry.getKey());
dailyRecord.setName(entry.getValue());
dailyRecord.setOpenPrice(BigDecimal.valueOf(array.getDoubleValue(2)));
dailyRecord.setHighest(BigDecimal.valueOf(array.getDoubleValue(3)));
dailyRecord.setLowest(BigDecimal.valueOf(array.getDoubleValue(4)));
dailyRecord.setClosePrice(BigDecimal.valueOf(array.getDoubleValue(5)));
dailyRecord.setIncreaseRate(BigDecimal.valueOf(array.getDoubleValue(7)));
dailyRecord.setAmount(array.getLongValue(9) / 10000);
dailyRecordMapper.insert(dailyRecord);
log.info("更新[ {} ]近日成交数据完成!", entry.getValue());
}
}
Thread.sleep(3000);
} catch (Exception e) {
}
});
}
while (executorService.getQueue().size() != 0) {
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
log.info("更新股票每日成交数据完成!");
}
Aggregations