我用MySQL创建了一个简单的Spring应用程序。
在数据库中,有20年的库存数据(5694行):

目标是为这20年的股票数据寻找最佳移动平均线(N)。投入是每个交易日的收盘价。计算的平均值取决于N. So体育。若N=3为参考日t的平均值,则由((t-1)+(t-2)+(t-3)/N)给出。输出是最佳移动平均线( N ),也是您在最佳N的所有买卖交易中取得的结果。
我在互联网上找不到合适的算法,所以我实现了以下几个步骤:
对于每N次(249次),程序执行以下步骤:
@Repository
public interface StockRepository extends CrudRepository<Stock, Integer> {
/*
* This sql query calculate the moving average of the value n
*/
@Query(value = "SELECT a.date, a.close, Round( ( SELECT SUM(b.close) / COUNT(b.close) FROM stock AS b WHERE DATEDIFF(a.date, b.date) BETWEEN 0 AND ?1 ), 2 ) AS 'avg' FROM stock AS a ORDER BY a.date", nativeQuery = true)
List<AverageDTO> calculateAverage(int n); 的比较结果
@RestController
public class ApiController {
@Autowired
private StockRepository stockRepository;
@CrossOrigin(origins = "*")
@GetMapping("/getBestValue")
/*
* This function tries all possible values in the interval [min,max], calculate
* the moving avg and simulate the gains for each value to choose the best one
*/
public ResultDTO getBestValue(@PathParam("min") int min, @PathParam("max") int max) {
Double best = 0.0;
int value = 0;
for (int i = min; i <= max; i++) {
Double result = simulate(stockRepository.calculateAverage(i));
if (result > best) {
value = i;
best = result;
}
}
return new ResultDTO(value, best);
}
/*
* This function get as input the close and moving average of a stock and
* simulate the buying/selling process
*/
public Double simulate(List<AverageDTO> list) {
Double result = 0.0;
Double lastPrice = list.get(0).getClose();
for (int i = 1; i < list.size(); i++) {
if (list.get(i - 1).getClose() < list.get(i - 1).getAvg()
&& list.get(i).getClose() > list.get(i).getAvg()) {
// buy
lastPrice = list.get(i).getClose();
} else if (list.get(i - 1).getClose() > list.get(i - 1).getAvg()
&& list.get(i).getClose() < list.get(i).getAvg()) {
// sell
result += (list.get(i).getClose() - lastPrice);
lastPrice = list.get(i).getClose();
}
}
return result;
}
}当我把Min=2和Max=250放在一起的时候,要花45分钟才能完成。因为我是Java & Spring的初学者,所以我不知道如何优化它。每次输入我都很高兴。
发布于 2022-07-09 22:40:30
该问题等价于寻找最佳移动N和。然后用N除以具有这样一个切片,然后下一个切片减去第一个值并向末尾添加一个新值。这可能会导致一种用a[i + N] - a[i] >= 0查找局部增长的算法。
然而,在这种情况下,一个简单的顺序有序查询
double[] slice = new double[N];
double sum = 0.0;就够了。(数据库上的跳过算法可能太复杂了。)
只需遍历表,将切片保持为窗口,保留N个值和键,并保持最大值。
使用原语类型double而不是对象包装器Double。
如果数据库传输是一个严重的因素,存储过程就可以了。将一个庞大的表保持为真正多的实体,只是为了最大限度地运行是很不幸的。
最好是有一个缩合表或更好的场与N值之和。
https://stackoverflow.com/questions/72924875
复制相似问题