using System; using System.Collections.Generic; using System.Globalization; using RserveCli; using TSLab.Script; using TSLab.Script.Handlers; using TSLab.Script.Helpers; namespace VaRScript { public class VaRScript : IExternalScript { private const int Period = 120; // период расчета значений private const double ConfidenceLevel = 0.95; // доверительный уровень private const int VarHorizont = 5; // на сколько предсказывать будем private const double BaseVolatility = 0.04; // базовый уровень волатильности выше которого не берем ничо public void Execute(IContext ctx, ISecurity sec) { var closePrices = sec.ClosePrices; var count = ctx.BarsCount; // инициализируем подключение using (var engine = new RConnection(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }))) { #region Расчет // производим расчеты кривых через R engine["closePrices"] = Sexp.Make(closePrices); var cmd = @"laggedClose <- c(closePrices[1], closePrices[1:length(closePrices)-1] ); closeLogs <- log(closePrices/laggedClose); library(TTR); meanForPeriod <- runMean(closeLogs, {0}); stDevForPeriod <- runSD(closeLogs, {0}); stDevForWeek <- runSD(closeLogs, 5); qNorm <- qnorm({2}, meanForPeriod, stDevForPeriod); futureVar <- closePrices*(1+qNorm*sqrt({1}))".Put(Period, VarHorizont, 1 - ConfidenceLevel); cmd = cmd.Replace(" ", ""); cmd = cmd.Replace("\n", ""); cmd = cmd.Replace("\r", ""); // надо очистить строку, иначе не работает engine.VoidEval(cmd); // извлекаем значения из R в наши переменные локальные var stDevForPeriod = engine.Eval("stDevForPeriod").ToNative() as IList; var stDevForWeek = engine.Eval("stDevForWeek").ToNative() as IList; var qnorm = engine.Eval("qNorm").ToNative() as IList; var futureVaR = engine.Eval("futureVar").ToNative() as IList; #endregion #region Торговля-с // Теперь пробуем торговать эту байду var trailStopHnd = new TrailStop() { TrailEnable = 2, StopLoss = 2, TrailLoss = 6 }; for (var i = ctx.TradeFromBar; i < count; i++) { var le = sec.Positions.GetLastActiveForSignal("LE"); if (le == null) { if (stDevForWeek[i] < stDevForPeriod[i] && futureVaR[i] < futureVaR[i - 15] && futureVaR[i] < futureVaR[i - 30] && stDevForPeriod[i] < BaseVolatility) { sec.Positions.BuyAtMarket(i + 1, 1, "LE"); } } else { //Волатильность>БВ&& VaR_Ln_Dist> VaR_Ln_Dist[i-30] if (stDevForPeriod[i] > BaseVolatility && futureVaR[i] > futureVaR[i - 30]) { le.CloseAtMarket(i + 1, "LX"); } else { var stopPrice = trailStopHnd.Execute(le, i); le.CloseAtStop(i + 1, stopPrice, 1, "LXS"); } } } #endregion #region Отрисовка // Отрисовка var color = new Color(System.Drawing.Color.Green.ToArgb()); var pane = ctx.First; pane.AddList("futureVar ({0})".Put(VarHorizont), futureVaR, ListStyles.LINE, color, LineStyles.SOLID, PaneSides.RIGHT); pane = ctx.CreatePane("Индикаторы", 25, false); color = new Color(System.Drawing.Color.Blue.ToArgb()); pane.AddList("Волатильность ({0})".Put(Period), stDevForPeriod, ListStyles.LINE, color, LineStyles.SOLID, PaneSides.RIGHT); color = new Color(System.Drawing.Color.SeaGreen.ToArgb()); pane.AddList("ВолатильностьНеделя ({0})".Put(5), stDevForWeek, ListStyles.LINE, color, LineStyles.SOLID, PaneSides.RIGHT); pane.UpdatePrecision(PaneSides.RIGHT, 4); color = new Color(System.Drawing.Color.Red.ToArgb()); pane.AddList("qnorm ({0})".Put(Period), qnorm, ListStyles.LINE, color, LineStyles.SOLID, PaneSides.LEFT); pane.UpdatePrecision(PaneSides.LEFT, 4); #endregion } } } public static class TradeHelper { public static string Put(this string str, params object[] args) { // Вводим культуру для того чтобы double числа не переводились как числа с запятой! Это гадит. return string.Format(CultureInfo.InvariantCulture, str, args); } } }