首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优化:找到最简单的移动平均线需要花费太多的时间。

优化:找到最简单的移动平均线需要花费太多的时间。
EN

Stack Overflow用户
提问于 2022-07-09 21:58:51
回答 1查看 96关注 0票数 0

我用MySQL创建了一个简单的Spring应用程序。

在数据库中,有20年的库存数据(5694行):

目标是为这20年的股票数据寻找最佳移动平均线(N)。投入是每个交易日的收盘价。计算的平均值取决于N. So体育。若N=3为参考日t的平均值,则由((t-1)+(t-2)+(t-3)/N)给出。输出是最佳移动平均线( N ),也是您在最佳N的所有买卖交易中取得的结果。

我在互联网上找不到合适的算法,所以我实现了以下几个步骤:

对于每N次(249次),程序执行以下步骤:

  1. SQL-查询:计算平均值&返回列表

代码语言:javascript
复制
@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); 

  1. 模拟买卖->计算结果

  1. 与bestResult

的比较结果

  1. Next N

代码语言:javascript
复制
@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的初学者,所以我不知道如何优化它。每次输入我都很高兴。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-09 22:40:30

该问题等价于寻找最佳移动N。然后用N除以具有这样一个切片,然后下一个切片减去第一个值并向末尾添加一个新值。这可能会导致一种用a[i + N] - a[i] >= 0查找局部增长的算法。

然而,在这种情况下,一个简单的顺序有序查询

代码语言:javascript
复制
double[] slice = new double[N];
double sum = 0.0;

就够了。(数据库上的跳过算法可能太复杂了。)

只需遍历表,将切片保持为窗口,保留N个值和键,并保持最大值。

使用原语类型double而不是对象包装器Double

如果数据库传输是一个严重的因素,存储过程就可以了。将一个庞大的表保持为真正多的实体,只是为了最大限度地运行是很不幸的。

最好是有一个缩合表或更好的场与N值之和。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72924875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档