c# - 加速此代码 — 192 万亿次 for() 循环

标签 c# .net algorithmic-trading

我有一个小程序,用于算法股票交易。该代码在我的 8 核台式机上必须循环大约 192 万亿次。我考虑过租一台 64 核机器来运行它,但它不符合成本效益。

这只是一小段代码。但是 for 循环必须在每个要计算的柱上循环(大约 180 万个),然后它循环检查匹配的列表大约有 80 万个项目。

目前我能想到的加快速度的唯一方法是删除匹配的项目,因为它只发生一次(日期时间)。

还有其他人有办法加快这段代码的速度吗?我的桌面巨兽花了大约 45 个小时来运行该程序的一次迭代。

基本上我正在做的是计算每个柱,查看当前柱的日期时间是否与我手动创建的 CSV 文件中的日期时间匹配。然后从列表对象中,我获取交易方向并设置一个 bool 值来建立仓位。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using ATCenterProxy.interop;
using System.IO;
using System.IO.Compression;

namespace PowerLanguage.Strategy
{
    public class Ecal_v1 : SignalObject
    {
        public List<Trades> tradeList = new List<Trades>();
        public List<string> csvList = new List<string>();
        public bool exitOn24 = false;
        public string ecalPath = @"C:\Users\Skynet\OneDrive\Trading\Economic Calendars\backtest1.csv";
        PowerLanguage.Indicator.Bollinger_Bands bb;

        public Ecal_v1(object _ctx):base(_ctx){}

        //[Input]
        //public bool exitOn24 { get; set; }

        [Input]
        public double bbTopOffset { get; set; }
        775
        [Input]
        public double bbBotOffset { get; set; }

        [Input]
        public double longTPMod { get; set; }

        [Input]
        public double shortTPMod { get; set; }

        [Input]
        public double longSLMod { get; set; }

        [Input]
        public double shortSLMod { get; set; }

        //[Input]
        //public double buyTrail { get; set; }

        //[Input]
        //public double sellTrail { get; set; }

        double bbUpperDiff;
        double bbLowerDiff;
        double bbBasis;
        double longTP;
        double shortTP;
        double longSL;
        double shortSL;
        double ptValue;
        public DateTime tradeTime;

        private IOrderMarket longEntry, shortEntry, longExit, shortExit;

        protected override void Create()
        {
            // create variable objects, function objects, order objects etc.
            bb = ((PowerLanguage.Indicator.Bollinger_Bands)AddIndicator("Bollinger_Bands"));

            longEntry = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Buy));
            shortEntry = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.SellShort));
            longExit = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Sell));
            shortExit = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover));
        }

        protected override void StartCalc()
        {
            // assign inputs 
            GetEcal();
            ptValue = Bars.Point;

            longTP = longTPMod;
            longSL = longSLMod;
            shortTP = shortTPMod;
            shortSL = shortSLMod;

        }

        protected override void CalcBar()
        {
            bool LE = false;
            bool SE = false;
            bool LX = false;
            bool SX = false;

            for(int i=0; i<tradeList.Count; i++)
            {
                if(Bars.Time[0] == tradeList.ElementAt(i).time)
                {
                    if (tradeList.ElementAt(i).direction == "Up")
                    {
                        LE = true;
                        tradeList.RemoveAt(i);
                    }
                    else if (tradeList.ElementAt(i).direction == "Down")
                    {
                        SE = true;
                        tradeList.RemoveAt(i);
                    }
                    else
                    {

                    }
                }
            }

            if(exitOn24 == true)
            {
                if (Bars.Time[0] > tradeTime.AddHours(24))
                {
                    LX = true;
                    SX = true;
                }
            }

            if (StrategyInfo.MarketPosition == 0)
            {
                if (LE)
                {
                    longEntry.Send();
                    tradeTime = Bars.Time[0];
                    setLongStops();     
                }
                else if (SE)
                {
                    shortEntry.Send();
                    tradeTime = Bars.Time[0];
                    setShortStops();        
                }
            }

            else if (StrategyInfo.MarketPosition > 0)
            {
                if (LX)
                {
                    longExit.Send();
                }
                else if (LE)
                {
                    longEntry.Send();
                    tradeTime = Bars.Time[0];
                    setLongStops();
                }
                else
                {
                    CurSpecOrdersMode = ESpecOrdersMode.PerPosition;
                    GenerateStopLossPt(longSL);
                    GenerateProfitTargetPt(longTP);
                    //GenerateTrailingStopPt(buyTrail);
                }
            }

            else if (StrategyInfo.MarketPosition < 0)
            {
                if (SX)
                {
                    shortExit.Send();
                }
                else if (SE)
                {
                    shortEntry.Send();
                    tradeTime = Bars.Time[0];
                    setShortStops();
                }
                else
                {
                    CurSpecOrdersMode = ESpecOrdersMode.PerPosition;
                    GenerateStopLossPt(shortSL);
                    GenerateProfitTargetPt(shortTP);
                    //GenerateTrailingStopPt(sellTrail);
                }
            }
        }

        private void GetEcal()
        {
            csvList = File.ReadAllLines(ecalPath).Skip(1).ToList();
            foreach(string line in csvList)
            {
                string[] values = line.Split(',');
                tradeList.Add(new Trades { time = Convert.ToDateTime(values[0]), direction = values[1] });
            }
        }
    }


    public class Trades
    {
        public DateTime time { get; set; }
        public string direction { get; set; }
    }


}

速度变慢的罪魁祸首是 CalcBar() 方法内的 For 循环。

最佳答案

您是否尝试过分析此方法?我们掌握的信息太少了。例如,成本最高的操作可能是

Bars.Time[0] == tradeList.ElementAt(i).time

我们不知道这一点。您应该首先对其进行概要分析。

下一步...

tradeList.ElementAt(i).direction == "Up"

不要使用字符串。弦很慢。您可以在这里使用枚举,它将针对整数进行优化,并且整数比较比字符串快得多。

不要使用ElementAt方法。仅使用 [] 运算符。速度更快了。

考虑使用字典而不是列表。它比列表快得多。列表必须遍历每个元素才能找到您需要的内容。字典没有。这可能是真正关键的部分。

考虑使用整数而不是日期时间。将整数视为秒。它会比 DateTime 更快。

并使用Parallel.ForEach代替普通的for。然后它将使用其他核心。普通的可能只使用一个核心。

哦,还有一件事。如果是股票应用,也许你可以尝试使用神经网络?但这是一个完全不同的故事。

关于c# - 加速此代码 — 192 万亿次 for() 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44196461/

相关文章:

python - 多交易所、多币种、多金额的套利算法

python - poloniex 中的 returnTradeHistory 总是返回空列表

c# - 尝试在 C# 中打开 Excel 工作表但未安装提供程序

c# - 如何从包含 5000 条记录的 Excel 文件插入到 documentDB?

c# - 使用 TransactionScope 的间歇性 System.ArgumentNullException

c# - 无法获取 DisplayAttribute 名称

python - 如何根据先前的状态在 pandas 数据框中创建列?

c# - 如何更新 .NET 中现有配置键的值?

c# - 如何使用 C# 向 OU 添加权限?

c# - 如何在鼠标按下时获取鼠标光标下的 TreeNode?