async Task FillTestParams(TradingMacro tmOriginal, Action <IList <KeyValuePair <string, object>[]> > paramsTransformation)
        {
            var c = _testParamValuesSeparators;

            if (!_testParamsRaw.Any())
            {
                if (!ReplayArguments.IsWww && tmOriginal.UseTestFile)
                {
                    var od = new Microsoft.Win32.OpenFileDialog()
                    {
                        FileName = "TestParams", DefaultExt = ".txt", Filter = "Text documents(.txt)|*.txt"
                    };
                    var odRes = od.ShowDialog();
                    if (!odRes.GetValueOrDefault())
                    {
                        throw new ArgumentException("Must provide test params file name.");
                    }
                    tmOriginal.TestFileName = System.IO.Path.GetFileName(od.FileName);
                    if (tmOriginal.TestFileName.Contains("skipme"))
                    {
                        tmOriginal.TestFileName = "";
                    }
                    else
                    {
                        var paramsDict = Lib.ReadTestParameters(od.FileName);
                        _testParamsRaw.AddRange(paramsDict.Select(kv => kv.Value.Split(c).Select(v => new KeyValuePair <string, object>(kv.Key, v)).ToArray()));
                    }
                }
                else if (ReplayArguments.IsWww)
                {
                    ReplayArguments.LastWwwError = "";
                    var strats = TaskMonad.RunSync(() => ReadStrategies(tmOriginal, (name, desc, content, uri, diff) => new { name, content, diff }));
                    Func <string, bool> isTest = s => s.ToLower().Trim().EndsWith("{t}");
                    await strats.Select(s => s.First())
                    .Take(2)
                    .OrderByDescending(s => isTest(s.name))
                    .Where(s => isTest(s.name) || s.diff.IsEmpty())
                    .OnEmpty(() => { LogWww(new Exception(ReplayArguments.LastWwwError = "Current settings don't match any strategy")); })
                    .Select(strategy => {
                        tmOriginal.TestFileName = strategy.name;
                        var paramsDict          = Lib.ReadParametersFromString(strategy.content);
                        _testParamsRaw.AddRange(
                            paramsDict
                            .Select(kv => kv.Value.Split(c).Select(v => new KeyValuePair <string, object>(kv.Key, v))
                                    .ToArray()));
                        return(tmOriginal.LoadActiveSettings(strategy.name, TradingMacro.ActiveSettingsStore.Gist));
                    }).WhenAll();
                }
                else
                {
                    var testParams = tmOriginal.GetPropertiesByAttibute <CategoryAttribute>(a => a.Category == TradingMacro.categoryTest);
                    var paramsDict = testParams.ToDictionary(p => p.Item2.Name.Substring(4), p => p.Item2.GetValue(tmOriginal, null).ToString().ParseParamRange());
                    _testParamsRaw.AddRange(paramsDict.Where(kv => !string.IsNullOrWhiteSpace(kv.Value))
                                            .Select(kv => kv.Value.Split(c).Select(v => new KeyValuePair <string, object>(kv.Key, v)).ToArray()));
                }
            }
            TestParams.Clear();
            paramsTransformation(_testParamsRaw);
            _testParamsRaw.CartesianProduct().ForEach(tp => TestParams.Enqueue(tp.ToArray()));
        }
        void SaveTradingSettings(TradingMacro tmOriginal)
        {
            try {
                var attrs = new[] { TradingMacro.categoryActive, TradingMacro.categoryActiveFuncs };
                tmOriginal.GetPropertiesByAttibute <CategoryAttribute>(a => attrs.Contains(a.Category))
                .GroupBy(a => a.Item2.Name).ToList().ForEach(g => {
                });

                //.ForEach(p => Debug.WriteLine("{0}={1}", p.Name, p.GetValue(tmOriginal, null)));
            } catch { }
        }