├── .github
└── workflows
│ ├── dotnet-core.yml
│ └── github-actions-demo.yml
├── .gitignore
├── BaseContextHandler.cs
├── ClusterAnalysis
├── AlignedSecurity.DataSourceSecurity.cs
├── AlignedSecurity.cs
├── AlignedSecurityHandler.cs
├── AllTimeTradeStatisticsHandler.cs
├── BaseTradeStatisticsHandler.cs
├── InteractiveSeriesHandler.cs
├── LastContractsTradeStatisticsHandler.cs
├── LastTradeStatisticsHandler.cs
├── MarketPosition.cs
├── SpecifiedQuantityPriceAtTradeHandler.cs
├── TradeStatisticsBarsCountHandler.cs
├── TradeStatisticsBarsHandler.cs
├── TradeStatisticsBarsSumHandler.cs
├── TradeStatisticsBaseExtendedBarsHandler.cs
├── TradeStatisticsBaseExtendedExtremumPriceHandler.cs
├── TradeStatisticsBaseExtremumPriceHandler.cs
├── TradeStatisticsCombine.cs
├── TradeStatisticsEdgeHandler.cs
├── TradeStatisticsExtendedBarsCountHandler.cs
├── TradeStatisticsExtendedBarsCountHandler2.cs
├── TradeStatisticsExtendedBarsHandler.cs
├── TradeStatisticsExtendedBarsHandler2.cs
├── TradeStatisticsExtendedBarsSumHandler.cs
├── TradeStatisticsExtendedBarsSumHandler2.cs
├── TradeStatisticsExtendedExtremumPriceHandler.cs
├── TradeStatisticsExtendedExtremumPriceHandler2.cs
├── TradeStatisticsExtremumPriceHandler.cs
├── TradeStatisticsExtremumValueHandler.cs
├── TradeStatisticsHandler.cs
├── TradeStatisticsLowerEdgeHandler.cs
├── TradeStatisticsPriceValueHandler.cs
└── TradeStatisticsUpperEdgeHandler.cs
├── ConstList.cs
├── Constants.cs
├── Cycle
├── AddPositionHandler.cs
├── CycleBoolHandler.cs
├── CycleHandler.cs
├── CycleResultHandler.cs
├── CycleResultsHandler.cs
└── CycleValueUpdaterHandler.cs
├── GraphPane
├── InteractiveConstGen.cs
├── InteractiveLineGen.BaseList.cs
├── InteractiveLineGen.ConstList.cs
├── InteractiveLineGen.LineList.cs
└── InteractiveLineGen.cs
├── HelperDescriptionAttribute.cs
├── HelperLinkAttribute.cs
├── HelperNameAttribute.cs
├── Indicators
├── ADX.cs
├── AMA.cs
├── Alligator.cs
├── Aroon.cs
├── BarsCountForValuesSumHandler.cs
├── BaseIndicator.cs
├── DoubleStreamAndValuesHandler.cs
├── MACD.cs
├── MAMA.cs
├── Momentum.cs
├── ParabolicSAR.cs
├── SomeIndicators.cs
├── SumForTimeFrameHandler.cs
├── TEMA.cs
└── Trix.cs
├── Logging.cs
├── Other
├── EmptyDoubleHandler.cs
├── Heartbeat.cs
├── TEST.cs
└── TickTest Handler.cs
├── PortfolioHandlers
├── AgentHandlers.cs
├── Portfolio.Enums.cs
└── Portfolio.cs
├── Position
├── HoldSignalForNBars.cs
├── PositionHandlers.cs
└── PositionHandlers2.cs
├── ProfitExtensions.cs
├── Properties
├── Resources.resx
└── Resources.ru.resx
├── README.md
├── ScriptCommonHandlers.csproj
├── Service
├── ControlMessageHandler.cs
├── EventKindHandler.cs
├── ExportValuesHandler.cs
├── FormatMessageHandler.cs
├── HeartbeatHandler.cs
├── HeartbeatManager.cs
├── ImportBoolValuesHandler.cs
├── ImportDoubleValuesHandler.cs
├── ImportIntValuesHandler.cs
├── ImportValuesHandler.cs
├── InstrumentByName.cs
├── InstrumentByNumber.cs
├── LoadFromGlobalCache2.cs
├── MessageHandler.cs
├── RecalcScheduler.cs
├── SaveToGlobalCache2.cs
└── TimestampHandler.cs
├── ShrinkedList.cs
├── TSChannel
├── BoolReceiverHandler.cs
├── ChannelHandler.cs
├── IsReceiverOnline.cs
├── ParameterSenderHandler.cs
├── ReceiverHandler.cs
├── ValueReceiverHandler.cs
└── ValueSenderHandler.cs
├── TradeMath
├── AccumHandlers.cs
├── BarNumber.cs
├── BarsConstructorBase.cs
├── BarsConstructorHandler.cs
├── BarsTickDataHandler.cs
├── Compress.cs
├── ConstGen.cs
├── ControlledBoolBreaker.cs
├── ControlledBoolConst.cs
├── ExtremePos.cs
├── FinInfoHandlers.cs
├── Ln.cs
├── Multiply.cs
├── OrderBookPrice.cs
├── OrderBookQty.cs
├── OrderBookTotal.cs
├── RandomHandler.cs
├── ResettableControlledBoolConst.cs
├── ResultForOptimization.cs
├── SecurityHandlers.cs
├── SessionBase.cs
├── Support.cs
├── TextHandler.cs
├── ValueSupportedIndicator.cs
└── WeightedAveragePrice.cs
├── ValueUpdaterExecutionOrder.cs
└── VolumeAnalysis
├── BuysHandler.cs
├── BuysMinusSellsHandler.cs
├── BuysSellsHandler.cs
├── SellsHandler.cs
├── ValueForPeriodHandler.cs
└── VolumeForPeriodHandler.cs
/.github/workflows/dotnet-core.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Setup .NET Core
17 | uses: actions/setup-dotnet@v1
18 | with:
19 | dotnet-version: 9.0.x
20 | - name: Restore packages
21 | run: dotnet restore
22 | - name: Pack
23 | run: dotnet pack --configuration Release
24 | - name: Publish
25 | id: publish_nuget
26 | uses: alirezanet/publish-nuget@v3.1.0
27 | with:
28 | PROJECT_FILE_PATH: ScriptCommonHandlers.csproj
29 | NUGET_KEY: ${{secrets.NUGET_API_KEY}}
30 |
--------------------------------------------------------------------------------
/.github/workflows/github-actions-demo.yml:
--------------------------------------------------------------------------------
1 | name: GitHub Actions Demo
2 | run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
3 | on: [push]
4 | jobs:
5 | Explore-GitHub-Actions:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
9 | - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
10 | - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
11 | - name: Check out repository code
12 | uses: actions/checkout@v4
13 | - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
14 | - run: echo "🖥️ The workflow is now ready to test your code on the runner."
15 | - name: List files in the repository
16 | run: |
17 | ls ${{ github.workspace }}
18 | - run: echo "🍏 This job's status is ${{ job.status }}."
19 |
--------------------------------------------------------------------------------
/ClusterAnalysis/AlignedSecurity.DataSourceSecurity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.DataSource;
3 |
4 | // ReSharper disable once CheckNamespace
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed partial class AlignedSecurity
8 | {
9 | private sealed class DataSourceSecurity : IDataSourceSecurity
10 | {
11 | private readonly IDataSourceSecurity m_source;
12 |
13 | public DataSourceSecurity(IDataSourceSecurity source)
14 | {
15 | m_source = source ?? throw new ArgumentNullException(nameof(source));
16 | }
17 |
18 | public string ToString(string format, IFormatProvider formatProvider)
19 | {
20 | return m_source + ".Aligned";
21 | }
22 |
23 | public string Id => m_source.Id;
24 |
25 | public string Name => m_source.Name;
26 |
27 | public string FullName => m_source.FullName;
28 |
29 | public string Comment => m_source.Comment;
30 |
31 | public string Currency => m_source.Currency;
32 |
33 | public IDataSourceTradePlace TradePlace => m_source.TradePlace;
34 |
35 | public string DSName => m_source.DSName + ".Aligned";
36 |
37 | public string ProviderName => m_source.ProviderName + ".Aligned";
38 |
39 | public double LotSize => m_source.LotSize;
40 |
41 | public double LotTick => m_source.LotTick;
42 |
43 | public double Margin => m_source.Margin;
44 |
45 | public int Decimals => m_source.Decimals;
46 |
47 | public int BalanceDecimals => m_source.BalanceDecimals;
48 |
49 | public int BalancePriceDecimals => m_source.BalancePriceDecimals;
50 |
51 | public double Tick => m_source.Tick;
52 |
53 | public double GetTick(double price)
54 | {
55 | throw new NotSupportedException();
56 | }
57 |
58 | public bool Expired => throw new NotSupportedException();
59 |
60 | public bool IsMoney => throw new NotSupportedException();
61 |
62 | public ActiveType ActiveType => throw new NotSupportedException();
63 |
64 | public bool IsOption => throw new NotSupportedException();
65 |
66 | public IDataSourceSecurity BaseSecurity => throw new NotSupportedException();
67 |
68 | public CalcSourceInfo CalcSecurity { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
69 |
70 | public double Strike => throw new NotSupportedException();
71 |
72 | public DateTime ExpirationDate => throw new NotSupportedException();
73 |
74 | public double ReducedPrice(double price) => m_source.ReducedPrice(price);
75 |
76 | public double ReducedPrice(double price, CalcSourceParams? calcParams)
77 | {
78 | return m_source.ReducedPrice(price, calcParams);
79 | }
80 |
81 | public double CalculatePnL(double entryPrice, double exitPrice, double lots)
82 | {
83 | return m_source.CalculatePnL(entryPrice, exitPrice, lots);
84 | }
85 |
86 | public double CalculatePnL(double entryPrice, double exitPrice, double lots, CalcSourceParams? calcParams)
87 | {
88 | return m_source.CalculatePnL(entryPrice, exitPrice, lots, calcParams);
89 | }
90 |
91 | public double GetCostPrice(CalcSourceParams? calcParams)
92 | {
93 | return m_source.GetCostPrice(calcParams);
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ClusterAnalysis/AlignedSecurityHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.DataSource;
3 | using TSLab.Script.Handlers.Options;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | // TODO: английское описание
8 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
9 | [HelperName("Aligned instrument", Language = Constants.En)]
10 | [HelperName("Выровненный инструмент", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.SECURITY)]
15 | [Description("Блок 'Выровненный инструмент' обеспечивает отображение гистограмм одинаковой ширины вне зависимости от фактического количества свечей в графике.")]
16 | [HelperDescription("", Constants.En)]
17 | public sealed class AlignedSecurityHandler : IAlignedSecurityHandler
18 | {
19 | ///
20 | /// \~english Timeframe (integer value in units of parameter 'Timeframe units')
21 | /// \~russian Интервал (целое число в единицах параметра 'База интервала')
22 | ///
23 | [HelperName("Timeframe", Constants.En)]
24 | [HelperName("Интервал", Constants.Ru)]
25 | [Description("Интервал (целое число в единицах параметра 'База интервала')")]
26 | [HelperDescription("Timeframe (integer value in units of parameter 'Timeframe units')", Constants.En)]
27 | [HandlerParameter(true, "1", Min = "1", Max = "365", Step = "1")]
28 | public int TimeFrame { get; set; }
29 |
30 | ///
31 | /// \~english Timeframe units (second, minute, hour, day)
32 | /// \~russian База интервала (секунды, минуты, часы, дни)
33 | ///
34 | [HelperName("Timeframe units", Constants.En)]
35 | [HelperName("База интервала", Constants.Ru)]
36 | [Description("База интервала (секунды, минуты, часы, дни)")]
37 | [HelperDescription("Timeframe units (second, minute, hour, day)", Constants.En)]
38 | [HandlerParameter(true, nameof(TimeFrameUnit.Hour))]
39 | public TimeFrameUnit TimeFrameUnit { get; set; }
40 |
41 | public ISecurity Execute(ISecurity security)
42 | {
43 | var timeFrame = TimeFrameFactory.Create(TimeFrame, TimeFrameUnit);
44 | return new AlignedSecurity(security, timeFrame);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ClusterAnalysis/AllTimeTradeStatisticsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | // TODO: английское описание
7 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
8 | [HelperName("All Time Trade Statistics", Language = Constants.En)]
9 | [HelperName("Торговая статистика за всё время", Language = Constants.Ru)]
10 | [InputsCount(1)]
11 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.TRADE_STATISTICS)]
14 | [Description("Блок 'Торговая статистика за всё время' создает гистограмму на основе всего доступного временного интервала. " +
15 | "[br]Гистограмма может быть построена на количестве сделок, объеме торгов, количестве покупок, количестве продаж, разнице количества покупок и продаж и относительной разнице количества покупок и продаж, % (см. параметр 'Вид').")]
16 | [HelperDescription("", Constants.En)]
17 | public sealed class AllTimeTradeStatisticsHandler : BaseTradeStatisticsHandler, IAllTimeTradeStatisticsHandler
18 | {
19 | ///
20 | /// \~english A width of a hystogram relative to a width of a chart pane.
21 | /// \~russian Ширина гистограммы в процентах относительно ширины панели графика.
22 | ///
23 | [HelperName("Width, %", Constants.En)]
24 | [HelperName("Ширина, %", Constants.Ru)]
25 | [Description("Ширина гистограммы в процентах относительно ширины панели графика.")]
26 | [HelperDescription("A width of a hystogram relative to a width of a chart pane.", Constants.En)]
27 | [HandlerParameter(true, "10", Min = "1", Max = "100", Step = "1", EditorMin = "1", EditorMax = "100")]
28 | public override double WidthPercent { get; set; }
29 |
30 | protected override ITradeStatisticsWithKind InternalExecute(ISecurity security)
31 | {
32 | var runTime = Context.Runtime;
33 | var id = runTime != null ? string.Join(".", runTime.TradeName, runTime.IsAgentMode, VariableId) : VariableId;
34 | var descriptionId = security.SecurityDescription?.Id ?? security.Symbol;
35 | var dsName = security.SecurityDescription?.DSName;
36 | if (dsName != null)
37 | descriptionId = $"{descriptionId}-{dsName}";
38 | var stateId = string.Join(".", descriptionId, security.Interval, security.IsAligned, CombinePricesCount);
39 | var tradeStatistics = Context.GetTradeStatistics(stateId, () => TradeStatisticsCache.Instance.GetAllTimeTradeStatistics(id, stateId, GetTradeHistogramsCache(security)));
40 | return new AllTimeTradeStatisticsWithKind(tradeStatistics, Kind, WidthPercent);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ClusterAnalysis/BaseTradeStatisticsHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | //[HandlerCategory(HandlerCategories.ClusterAnalysis)]
10 | // Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов. Это снижает гибкость управления в перспективе.
11 | public abstract class BaseTradeStatisticsHandler : IBaseTradeStatisticsHandler
12 | where TTradeStatisticsWithKind : IBaseTradeStatisticsWithKind
13 | {
14 | public string VariableId { get; set; } = string.Empty;
15 |
16 | public IContext Context { get; set; }
17 |
18 | ///
19 | /// \~english How many price steps should be grouped together.
20 | /// \~russian Осуществление выбора шага цены, используемого для группировки цен.
21 | ///
22 | [HelperName("Combine price steps", Constants.En)]
23 | [HelperName("Объединять шаги цены", Constants.Ru)]
24 | [Description("Осуществление выбора шага цены, используемого для группировки цен.")]
25 | [HelperDescription("How many price steps should be grouped together.", Constants.En)]
26 | [HandlerParameter(true, "1", Min = "1", Max = "10", Step = "1", EditorMin = "1")]
27 | public int CombinePricesCount { get; set; }
28 |
29 | ///
30 | /// \~english Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).
31 | /// \~russian Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).
32 | ///
33 | [HelperName("Kind", Constants.En)]
34 | [HelperName("Вид", Constants.Ru)]
35 | [Description("Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).")]
36 | [HelperDescription("Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).", Constants.En)]
37 | [HandlerParameter(true, nameof(TradeStatisticsKind.TradesCount))]
38 | public TradeStatisticsKind Kind { get; set; }
39 |
40 | ///
41 | /// \~english A width of a hystogram relative to a width of a chart pane.
42 | /// \~russian Ширина гистограммы в процентах относительно ширины панели графика.
43 | ///
44 | [HelperName("Width, %", Constants.En)]
45 | [HelperName("Ширина, %", Constants.Ru)]
46 | [Description("Ширина гистограммы в процентах относительно ширины панели графика.")]
47 | [HelperDescription("A width of a hystogram relative to a width of a chart pane.", Constants.En)]
48 | [HandlerParameter(true, "100", Min = "1", Max = "100", Step = "1", EditorMin = "1", EditorMax = "100")]
49 | public virtual double WidthPercent { get; set; }
50 |
51 | public TTradeStatisticsWithKind Execute(ISecurity security)
52 | {
53 | if (security == null)
54 | throw new ArgumentNullException(nameof(security));
55 | var sw = Stopwatch.StartNew();
56 | try
57 | {
58 | var decompressedSecurity = Context.Runtime.Securities.First(
59 | item => item.SecurityDescription.Id == security.SecurityDescription.Id
60 | && item.SecurityDescription.DSName == security.SecurityDescription.DSName);
61 | return InternalExecute(decompressedSecurity);
62 | }
63 | finally
64 | {
65 | if (sw.Elapsed.TotalSeconds > 5)
66 | Context?.Log($"Time elapsed {this.GetType().Name}: {sw.Elapsed}", MessageType.Debug);
67 | }
68 | }
69 |
70 | protected abstract TTradeStatisticsWithKind InternalExecute(ISecurity security);
71 |
72 | protected ITradeHistogramsCache GetTradeHistogramsCache(ISecurity security)
73 | {
74 | var result = TradeHistogramsCaches.Instance.GetTradeHistogramsCache(Context, security, CombinePricesCount);
75 | return result;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/ClusterAnalysis/InteractiveSeriesHandler.cs:
--------------------------------------------------------------------------------
1 | #if DEBUG
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 |
6 | using TSLab.Script.CanvasPane;
7 | using TSLab.Script.Handlers.Options;
8 |
9 | namespace TSLab.Script.Handlers
10 | {
11 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
12 | [HelperName("InteractiveSeriesHandler", Language = Constants.En)]
13 | [HelperName("InteractiveSeriesHandler", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.INTERACTIVESPLINE)]
18 | [Description("БЕЗ ОПИСАНИЯ (кубик виден только в девелоперской версии)")]
19 | [HelperDescription("БЕЗ ОПИСАНИЯ (кубик виден только в девелоперской версии)", Constants.En)]
20 | #if !DEBUG
21 | [HandlerInvisible]
22 | #endif
23 | public sealed class InteractiveSeriesHandler : IOneSourceHandler, IStreamHandler, ISecurityInputs
24 | {
25 | public InteractiveSeries Execute(ISecurity security)
26 | {
27 | var interactiveObjects = new List();
28 | for (byte i = 0; i < 31; i++)
29 | {
30 | var j = (byte)(i << 3);
31 | var interactivePointActive = new InteractivePointActive(i, i)
32 | {
33 | BackColor = new Color(j, 0, 0),
34 | ForeColor = new Color(0, j, 0),
35 |
36 | IsActive = true,
37 | Label = i.ToString(),
38 | Color = new AlphaColor(255, j, 0, 0),
39 | DateTime = DateTime.UtcNow.AddDays(1),
40 |
41 | ValueXBackColor = new AlphaColor(255, j, 0, 0),
42 | ValueXForeColor = new AlphaColor(255, 0, j, 0),
43 |
44 | ValueYBackColor = new AlphaColor(255, 0, j, 0),
45 | ValueYForeColor = new AlphaColor(255, 0, 0, j),
46 |
47 | DateTimeBackColor = new AlphaColor(255, 0, 0, j),
48 | DateTimeForeColor = new AlphaColor(255, j, 0, 0),
49 | };
50 | interactiveObjects.Add(new InteractiveObject { Anchor = interactivePointActive });
51 | }
52 | return new InteractiveSeries(interactiveObjects);
53 | }
54 | }
55 | }
56 | #endif
57 |
--------------------------------------------------------------------------------
/ClusterAnalysis/LastContractsTradeStatisticsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | // TODO: английское описание
7 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
8 | [HelperName("Last Contracts Trade Statistics", Language = Constants.En)]
9 | [HelperName("Торговая статистика последних контрактов", Language = Constants.Ru)]
10 | [InputsCount(1)]
11 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
14 | [Description("Блок 'Торговая статистика последних контрактов' создает гистограмму за указанное количество последних контрактов.")]
15 | [HelperDescription("", Constants.En)]
16 | public sealed class LastContractsTradeStatisticsHandler : BaseTradeStatisticsHandler, ILastContractsTradeStatisticsHandler
17 | {
18 | ///
19 | /// \~english A parameter to set contracts count to be used for trade statistics.
20 | /// \~russian Осуществляет выбор количества контрактов, за которые должна отображаться торговая статистика.
21 | ///
22 | [HelperName("Contracts count", Constants.En)]
23 | [HelperName("Количество контрактов", Constants.Ru)]
24 | [Description("Осуществляет выбор количества контрактов, за которые должна отображаться торговая статистика.")]
25 | [HelperDescription("A parameter to set contracts count to be used for trade statistics.", Constants.En)]
26 | [HandlerParameter(true, "10000", Min = "10000", Max = "1000000", Step = "10000", EditorMin = "1")]
27 | public int ContractsCount { get; set; }
28 |
29 | protected override ILastContractsTradeStatisticsWithKind InternalExecute(ISecurity security)
30 | {
31 | var runTime = Context.Runtime;
32 | var id = runTime != null ? string.Join(".", runTime.TradeName, runTime.IsAgentMode, VariableId) : VariableId;
33 | var descriptionId = security.SecurityDescription?.Id ?? security.Symbol;
34 | var dsName = security.SecurityDescription?.DSName;
35 | if (dsName != null)
36 | descriptionId = $"{descriptionId}-{dsName}";
37 | var stateId = string.Join(".", descriptionId, security.Interval, security.IsAligned, CombinePricesCount, ContractsCount);
38 | var tradeStatistics = Context.GetLastContractsTradeStatistics(stateId, () => new LastContractsTradeStatistics(id, stateId, GetTradeHistogramsCache(security), ContractsCount));
39 | return new LastContractsTradeStatisticsWithKind(tradeStatistics, Kind, WidthPercent);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ClusterAnalysis/LastTradeStatisticsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.DataSource;
3 | using TSLab.Script.Handlers.Options;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | // TODO: английское описание
8 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
9 | [HelperName("Last Trade Statistics", Language = Constants.En)]
10 | [HelperName("Последняя торговая статистика", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.TRADE_STATISTICS)]
15 | [Description("Блок 'Последняя торговая статистика' создает гистограмму за указанный временной интервал.")]
16 | [HelperDescription("", Constants.En)]
17 | public sealed class LastTradeStatisticsHandler : BaseTradeStatisticsHandler, ITradeStatisticsHandler
18 | {
19 | [HandlerParameter(true, nameof(TimeFrameKind.FromMidnightToNow))]
20 | public TimeFrameKind TimeFrameKind { get; set; }
21 |
22 | ///
23 | /// \~english Timeframe (integer value in units of parameter 'Timeframe units')
24 | /// \~russian Интервал (целое число в единицах параметра 'База интервала')
25 | ///
26 | [HelperName("Timeframe", Constants.En)]
27 | [HelperName("Интервал", Constants.Ru)]
28 | [Description("Интервал (целое число в единицах параметра 'База интервала')")]
29 | [HelperDescription("Timeframe (integer value in units of parameter 'Timeframe units')", Constants.En)]
30 | [HandlerParameter(true, "1", Min = "1", Max = "365", Step = "1", EditorMin = "1")]
31 | public int TimeFrame { get; set; }
32 |
33 | ///
34 | /// \~english Timeframe units (second, minute, hour, day)
35 | /// \~russian База интервала (секунды, минуты, часы, дни)
36 | ///
37 | [HelperName("Timeframe units", Constants.En)]
38 | [HelperName("База интервала", Constants.Ru)]
39 | [Description("База интервала (секунды, минуты, часы, дни)")]
40 | [HelperDescription("Timeframe units (second, minute, hour, day)", Constants.En)]
41 | [HandlerParameter(true, nameof(TimeFrameUnit.Hour))]
42 | public TimeFrameUnit TimeFrameUnit { get; set; }
43 |
44 | [HandlerParameter(true, "0", Min = "0", Max = "365", Step = "1", EditorMin = "0")]
45 | public int TimeFrameShift { get; set; }
46 |
47 | [HandlerParameter(true, nameof(TimeFrameUnit.Hour))]
48 | public TimeFrameUnit TimeFrameShiftUnit { get; set; }
49 |
50 | protected override ITradeStatisticsWithKind InternalExecute(ISecurity security)
51 | {
52 | var interval = TimeFrameFactory.GetInterval(TimeFrame, TimeFrameUnit);
53 | var intervalShift = TimeFrameShift > 0 ? TimeFrameFactory.GetInterval(TimeFrameShift, TimeFrameShiftUnit) : null;
54 |
55 | var runTime = Context.Runtime;
56 | var id = runTime != null
57 | ? string.Join(".", runTime.TradeName, runTime.IsAgentMode, VariableId)
58 | : VariableId;
59 |
60 | var descriptionId = security.SecurityDescription?.Id ?? security.Symbol;
61 | var dsName = security.SecurityDescription?.DSName;
62 | if (dsName != null)
63 | descriptionId = $"{descriptionId}-{dsName}";
64 | var stateId = string.Join(".", descriptionId, security.Interval, security.IsAligned, CombinePricesCount,
65 | TimeFrameKind, TimeFrame, TimeFrameUnit, TimeFrameShift, TimeFrameShiftUnit);
66 |
67 | var tradeStatistics = Context.GetTradeStatistics(stateId,
68 | () => new LastTradeStatistics(id, stateId, GetTradeHistogramsCache(security), TimeFrameKind,
69 | TimeFrameUnit, TimeFrameShiftUnit, interval, intervalShift));
70 |
71 | return new TradeStatisticsWithKind(tradeStatistics, Kind, WidthPercent);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/ClusterAnalysis/SpecifiedQuantityPriceAtTradeHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.DataSource;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
10 | public sealed class SpecifiedQuantityPriceAtTradeHandler : ISpecifiedQuantityPriceAtTradeHandler
11 | {
12 | public IContext Context { get; set; }
13 |
14 | [HandlerParameter(true, "0", Min = "0", Max = "2147483647", Step = "1", EditorMin = "0", EditorMax = "2147483647")]
15 | public double Quantity { get; set; }
16 |
17 | [HandlerParameter(true, nameof(SpecifiedTradeDirection.Any))]
18 | public SpecifiedTradeDirection Direction { get; set; }
19 |
20 | public IList Execute(ISecurity security)
21 | {
22 | Func isValidTradeFunc;
23 | if (Direction == SpecifiedTradeDirection.Any)
24 | isValidTradeFunc = IsValidAnyTrade;
25 | else if (Direction == SpecifiedTradeDirection.Buy)
26 | isValidTradeFunc = IsValidBuyTrade;
27 | else if (Direction == SpecifiedTradeDirection.Sell)
28 | isValidTradeFunc = IsValidSellTrade;
29 | else
30 | throw new InvalidEnumArgumentException(nameof(Direction), (int)Direction, typeof(SpecifiedTradeDirection));
31 |
32 | var barsCount = Context.BarsCount;
33 | var results = Context.GetArray(barsCount);
34 | var tradesCache = Context.GetTradesCache(security);
35 | var price = 0D;
36 |
37 | for (var i = 0; i < barsCount; i++)
38 | {
39 | var trade = tradesCache.GetTrades(i).LastOrDefault(isValidTradeFunc);
40 | if (trade != null)
41 | price = trade.Price;
42 |
43 | results[i] = price;
44 | }
45 | return results;
46 | }
47 |
48 | private bool IsValidAnyTrade(ITrade trade)
49 | {
50 | return trade.Quantity > Quantity;
51 | }
52 |
53 | private bool IsValidBuyTrade(ITrade trade)
54 | {
55 | return trade.Direction == TradeDirection.Buy && trade.Quantity > Quantity;
56 | }
57 |
58 | private bool IsValidSellTrade(ITrade trade)
59 | {
60 | return trade.Direction == TradeDirection.Sell && trade.Quantity > Quantity;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsBarsCountHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Strings Count", Language = Constants.En)]
12 | [HelperName("Количество строк торговой статистики", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок 'Количество строк торговой статистики' выдает количество строк торговой статистики, соответствующее выбранному фильтру.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsBarsCountHandler : TradeStatisticsBarsHandler, ITradeStatisticsBarsCountHandler
20 | {
21 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
22 | {
23 | return bars.Count();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsBarsSumHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | // TODO: удачно ли здесь использовать слово 'string' как перевод слова 'строка'?
11 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
12 | [HelperName("Trade Statistics Strings Sum", Language = Constants.En)]
13 | [HelperName("Сумма строк торговой статистики", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.DOUBLE)]
18 | [Description("Блок 'Сумма строк торговой статистики' выдает значение, основанное на сумме значений строк торговой статистики.")]
19 | [HelperDescription("", Constants.En)]
20 | public sealed class TradeStatisticsBarsSumHandler : TradeStatisticsBarsHandler, ITradeStatisticsBarsCountHandler
21 | {
22 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
23 | {
24 | return bars.Sum(item => tradeStatistics.GetValue(item));
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsBaseExtremumPriceHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Globalization;
5 | using System.Linq;
6 | using TSLab.Script.Handlers.Options;
7 |
8 | // ReSharper disable once CheckNamespace
9 | namespace TSLab.Script.Handlers
10 | {
11 | //[HandlerCategory(HandlerCategories.ClusterAnalysis)]
12 | // Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов. Это снижает гибкость управления в перспективе.
13 |
14 | ///
15 | /// Базовый класс для расчета экстремумов торговой стаистистики.
16 | /// На вход подается Торговая Статистика, на выход идут числа.
17 | ///
18 | public abstract class TradeStatisticsBaseExtremumPriceHandler : ITradeStatisticsBaseExtremumPriceHandler
19 | {
20 | protected sealed class Extremum
21 | {
22 | public Extremum(ITradeHistogramBar bar, double value, double price)
23 | {
24 | Bar = bar;
25 | Value = value;
26 | Price = price;
27 | }
28 |
29 | public ITradeHistogramBar Bar { get; }
30 | public double Value { get; }
31 | public double Price { get; }
32 | }
33 |
34 | public string VariableId { get; set; }
35 |
36 | public IContext Context { get; set; }
37 |
38 | ///
39 | /// \~english Extremum kind (minimum, maximum).
40 | /// \~russian Вид экстремума (минимум, максимум).
41 | ///
42 | [HelperName("Extremum kind", Constants.En)]
43 | [HelperName("Вид экстремума", Constants.Ru)]
44 | [Description("Вид экстремума (минимум, максимум)")]
45 | [HelperDescription("Extremum kind (minimum, maximum).", Constants.En)]
46 | [HandlerParameter(true, nameof(ExtremumPriceMode.Minimum))]
47 | public ExtremumPriceMode PriceMode { get; set; }
48 |
49 | [HelperName("Min Bar, %", Constants.En)]
50 | [HelperName("Минимальный бар, %", Constants.Ru)]
51 | [HandlerParameter(true, "0", Min = "0", Max = "100", Step = "1", EditorMin = "0")]
52 | public double MinBarPct { get; set; }
53 |
54 | [HelperName("Max Bar, %", Constants.En)]
55 | [HelperName("максимальный бар, %", Constants.Ru)]
56 | [HandlerParameter(true, "100", Min = "0", Max = "100", Step = "1", EditorMin = "0")]
57 | public double MaxBarPct { get; set; } = 100;
58 |
59 | public abstract IList Execute(IBaseTradeStatisticsWithKind tradeStatistics);
60 |
61 | protected Extremum GetExtremum(IBaseTradeStatisticsWithKind tradeStatistics,
62 | IAggregatedHistogramBarsProvider aggregatedHistogramBarsProvider, int barIndex,
63 | ref double lastPrice)
64 | {
65 | var bars = aggregatedHistogramBarsProvider.GetAggregatedHistogramBars(barIndex);
66 | if (bars.Count == 0)
67 | return new Extremum(null, double.NaN, lastPrice);
68 |
69 | if (bars.Count == 1)
70 | {
71 | var bar = bars[0];
72 | return new Extremum(bar, Math.Abs(tradeStatistics.GetValue(bar)), lastPrice = bar.AveragePrice);
73 | }
74 |
75 | var minBar = (int)(bars.Count * MinBarPct / 100.0);
76 | var maxBar = (int)(bars.Count * MaxBarPct / 100.0);
77 | var count = maxBar - minBar;
78 |
79 | var reverse = PriceMode == ExtremumPriceMode.Maximum;
80 | var start = reverse ? bars.Count - minBar - 1 : minBar;
81 | var step = reverse ? -1 : 1;
82 |
83 | var extremumBar = bars[start];
84 | var extremumValue = Math.Abs(tradeStatistics.GetValue(extremumBar));
85 |
86 | for (int i = start, k = 0; k++ < count - 1;)
87 | {
88 | var bar = bars[i += step];
89 | var value = Math.Abs(tradeStatistics.GetValue(bar));
90 | if (extremumValue >= value)
91 | continue;
92 | extremumBar = bar;
93 | extremumValue = value;
94 | }
95 |
96 | return new Extremum(extremumBar, extremumValue, lastPrice = extremumBar.AveragePrice);
97 | }
98 |
99 | protected virtual string GetParametersStateId()
100 | {
101 | return string.Join(".", PriceMode.ToString(), MinBarPct.ToString(CultureInfo.InvariantCulture),
102 | MaxBarPct.ToString(CultureInfo.InvariantCulture));
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsCombine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using TSLab.DataSource;
7 | using TSLab.Script.Handlers.Options;
8 |
9 | namespace TSLab.Script.Handlers.ClusterAnalysis
10 | {
11 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
12 | [HelperName("Stacked Trading Statistics", Language = Constants.En)]
13 | [HelperName("Сложенная Торговая статистика", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.TRADE_STATISTICS)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.TRADE_STATISTICS)]
18 | [Description("Блок 'Сложенная Торговая статистика' складывает последние N, поданных на вход.")]
19 | [HelperDescription("", Constants.En)]
20 | public sealed class TradeStatisticsCombineHandler : BasePeriodIndicatorHandler,
21 | IOneSourceHandler,
22 | IStreamHandler,
23 | INeedVariableId,
24 | IContextUses,
25 | ITradeStatisticsReturns
26 | {
27 | public ITradeStatisticsWithKind Execute(ITradeStatisticsWithKind input)
28 | {
29 | if (input == null)
30 | throw new ArgumentNullException(nameof(input));
31 |
32 | var runTime = Context.Runtime;
33 | var id = runTime != null
34 | ? string.Join(".", runTime.TradeName, runTime.IsAgentMode, VariableId)
35 | : VariableId;
36 | var stateId = string.Join(".", input.StateId, Period);
37 | var tradeStatistics = Context.GetTradeStatistics(stateId,
38 | () => new TradeStatisticsCombine(id, stateId, Period, input));
39 | return new TradeStatisticsWithKind(tradeStatistics, input.Kind, input.WidthPercent);
40 | }
41 |
42 | public string VariableId { get; set; }
43 |
44 | public IContext Context { get; set; }
45 | }
46 |
47 | public sealed class TradeStatisticsCombine : BaseTradeStatistics, ITradeStatistics
48 | {
49 | private readonly ITradeStatisticsWithKind m_input;
50 |
51 | public TradeStatisticsCombine(string id, string stateId, int period, ITradeStatisticsWithKind input)
52 | : base(id, stateId, new TradeHistogramSettings(input.TradeHistogramsCache,
53 | TimeFrameKind.FromMidnightToNow, input.GetTimeFrameUnit(), new Interval(period, DataIntervals.MINUTE)))
54 | {
55 | m_input = input;
56 | CalculateHistograms();
57 | }
58 |
59 | public override bool HasStaticTimeline => m_input.HasStaticTimeline;
60 |
61 | protected override IReadOnlyList CalculateHistograms()
62 | {
63 | var histograms = new List();
64 |
65 | var queue = new Queue();
66 | var period = m_histogramSettings.Interval.Value;
67 | foreach (var histogram in m_input.GetHistograms())
68 | {
69 | if (queue.Count >= period)
70 | queue.Dequeue();
71 | queue.Enqueue(histogram);
72 |
73 | histograms.Add(new CombinedHistogram(m_histogramSettings, queue.First(), queue.Last()));
74 | }
75 |
76 | Parallel.ForEach(histograms.Where(item => !item.IsCalculated), (item) => item.Recalculate());
77 |
78 | m_histograms = histograms;
79 | return histograms;
80 | }
81 |
82 | public TimeSpan TimeFrameShift => m_input.TimeFrameShift;
83 |
84 | public TimeFrameUnit GetTimeFrameUnit() => m_input.GetTimeFrameUnit();
85 |
86 | public override ITradeHistogram GetLastHistogram()
87 | {
88 | return m_histograms.LastOrDefault();
89 | }
90 | }
91 |
92 | public class CombinedHistogram : BaseRefreshableTradeHistogram
93 | {
94 | public override int RealFirstBarIndex { get; }
95 |
96 | internal CombinedHistogram(TradeHistogramSettings histogramSettings, ITradeHistogram first, ITradeHistogram last)
97 | : base(histogramSettings)
98 | {
99 | RealFirstBarIndex = first.FirstBarIndex;
100 | FirstBarIndex = last.FirstBarIndex;
101 | LastBarIndex = last.LastBarIndex;
102 | LowDate = first.LowDate;
103 | HighDate = last.HighDate;
104 | }
105 |
106 | protected override IReadOnlyList GetCachedTradeHistograms()
107 | {
108 | return TradeHistogramsCache.GetHistograms(RealFirstBarIndex, LastBarIndex);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsCountHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | // TODO: удачно ли здесь использовать слово 'string' как перевод слова 'строка'?
11 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
12 | [HelperName("Trade Statistics Extended Strings Count 1", Language = Constants.En)]
13 | [HelperName("Расширенное количество строк торговой статистики 1", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.DOUBLE)]
18 | [Description("Блок 'Расширенное количество строк торговой статистики 1' выдает количество строк торговой статистики, соответствующее выбранному фильтру.")]
19 | [HelperDescription("", Constants.En)]
20 | public sealed class TradeStatisticsExtendedBarsCountHandler : TradeStatisticsExtendedBarsHandler, ITradeStatisticsExtendedBarsCountHandler
21 | {
22 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
23 | {
24 | return bars.Count();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsCountHandler2.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Extended Strings Count 2", Language = Constants.En)]
12 | [HelperName("Расширенное количество строк торговой статистики 2", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок 'Расширенное количество строк торговой статистики 2' выдает количество строк торговой статистики, соответствующее выбранному фильтру.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsExtendedBarsCountHandler2 : TradeStatisticsExtendedBarsHandler2, ITradeStatisticsExtendedBarsCountHandler2
20 | {
21 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
22 | {
23 | return bars.Count();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 |
4 | using TSLab.Script.Handlers.Options;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | // Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов
9 | public abstract class TradeStatisticsExtendedBarsHandler : TradeStatisticsBaseExtendedBarsHandler, ITradeStatisticsExtendedBarsHandler
10 | {
11 | [HandlerParameter(true, NotOptimized = true)]
12 | public bool UseTrimTradesCount { get; set; }
13 |
14 | [HandlerParameter(true, "0", Min = "0", Max = "2147483647", Step = "1", EditorMin = "0")]
15 | public int TrimTradesCount { get; set; }
16 |
17 | [HandlerParameter(true, NotOptimized = true)]
18 | public bool UseTrimQuantity { get; set; }
19 |
20 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
21 | public double TrimQuantity { get; set; }
22 |
23 | [HandlerParameter(true, NotOptimized = true)]
24 | public bool UseTrimAskQuantity { get; set; }
25 |
26 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
27 | public double TrimAskQuantity { get; set; }
28 |
29 | [HandlerParameter(true, NotOptimized = true)]
30 | public bool UseTrimBidQuantity { get; set; }
31 |
32 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
33 | public double TrimBidQuantity { get; set; }
34 |
35 | [HandlerParameter(true, NotOptimized = true)]
36 | public bool UseTrimDeltaAskBidQuantity { get; set; }
37 |
38 | [HandlerParameter(true, "0", Min = "-999999999999999", Max = "999999999999999", Step = "1")]
39 | public double TrimDeltaAskBidQuantity { get; set; }
40 |
41 | [HandlerParameter(true, "false", NotOptimized = true)]
42 | public bool UseTrimRelativeDeltaAskBidQuantityPercent { get; set; }
43 |
44 | [HandlerParameter(true, "0", Min = "-100", Max = "100", Step = "1")]
45 | public double TrimRelativeDeltaAskBidQuantityPercent { get; set; }
46 |
47 | ///
48 | /// \~english Comparison operator for trimming (greater, greater or equal, less, less or equal, equal, not equal).
49 | /// \~russian Оператор сравнения для формирования отсечек (больше, больше или равно, меньше, меньше или равно, равно, не равно).
50 | ///
51 | [HelperName("Comparison operator", Constants.En)]
52 | [HelperName("Режим сравнения отсечки", Constants.Ru)]
53 | [Description("Оператор сравнения для формирования отсечек (больше, больше или равно, меньше, меньше или равно, равно, не равно).")]
54 | [HelperDescription("Comparison operator for trimming (greater, greater or equal, less, less or equal, equal, not equal).", Constants.En)]
55 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
56 | public ComparisonMode TrimComparisonMode { get; set; }
57 |
58 | public IList Execute(IBaseTradeStatisticsWithKind tradeStatistics)
59 | {
60 | return Execute(
61 | tradeStatistics,
62 | new TrimContext(UseTrimTradesCount, TrimTradesCount, TrimComparisonMode),
63 | new TrimContext(UseTrimQuantity, TrimQuantity, TrimComparisonMode),
64 | new TrimContext(UseTrimAskQuantity, TrimAskQuantity, TrimComparisonMode),
65 | new TrimContext(UseTrimBidQuantity, TrimBidQuantity, TrimComparisonMode),
66 | new TrimContext(UseTrimDeltaAskBidQuantity, TrimDeltaAskBidQuantity, TrimComparisonMode),
67 | new TrimContext(UseTrimRelativeDeltaAskBidQuantityPercent, TrimRelativeDeltaAskBidQuantityPercent, TrimComparisonMode));
68 | }
69 |
70 | protected override string GetParametersStateId()
71 | {
72 | return string.Join(
73 | ".",
74 | UseTrimTradesCount,
75 | TrimTradesCount,
76 | UseTrimQuantity,
77 | TrimQuantity,
78 | UseTrimAskQuantity,
79 | TrimAskQuantity,
80 | UseTrimBidQuantity,
81 | TrimBidQuantity,
82 | UseTrimDeltaAskBidQuantity,
83 | TrimDeltaAskBidQuantity,
84 | UseTrimRelativeDeltaAskBidQuantityPercent,
85 | TrimRelativeDeltaAskBidQuantityPercent,
86 | TrimComparisonMode);
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsHandler2.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace TSLab.Script.Handlers
4 | {
5 | // Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов
6 | public abstract class TradeStatisticsExtendedBarsHandler2 : TradeStatisticsBaseExtendedBarsHandler, ITradeStatisticsExtendedBarsHandler2
7 | {
8 | [HandlerParameter(true, NotOptimized = true)]
9 | public bool UseTrimTradesCount { get; set; }
10 |
11 | [HandlerParameter(true, "0", Min = "0", Max = "2147483647", Step = "1", EditorMin = "0")]
12 | public int TrimTradesCount { get; set; }
13 |
14 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
15 | public ComparisonMode TrimTradesCountComparisonMode { get; set; }
16 |
17 | [HandlerParameter(true, NotOptimized = true)]
18 | public bool UseTrimQuantity { get; set; }
19 |
20 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
21 | public double TrimQuantity { get; set; }
22 |
23 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
24 | public ComparisonMode TrimQuantityComparisonMode { get; set; }
25 |
26 | [HandlerParameter(true, NotOptimized = true)]
27 | public bool UseTrimAskQuantity { get; set; }
28 |
29 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
30 | public double TrimAskQuantity { get; set; }
31 |
32 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
33 | public ComparisonMode TrimAskQuantityComparisonMode { get; set; }
34 |
35 | [HandlerParameter(true, NotOptimized = true)]
36 | public bool UseTrimBidQuantity { get; set; }
37 |
38 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
39 | public double TrimBidQuantity { get; set; }
40 |
41 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
42 | public ComparisonMode TrimBidQuantityComparisonMode { get; set; }
43 |
44 | [HandlerParameter(true, NotOptimized = true)]
45 | public bool UseTrimDeltaAskBidQuantity { get; set; }
46 |
47 | [HandlerParameter(true, "0", Min = "-999999999999999", Max = "999999999999999", Step = "1")]
48 | public double TrimDeltaAskBidQuantity { get; set; }
49 |
50 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
51 | public ComparisonMode TrimDeltaAskBidQuantityComparisonMode { get; set; }
52 |
53 | [HandlerParameter(true, "false", NotOptimized = true)]
54 | public bool UseTrimRelativeDeltaAskBidQuantityPercent { get; set; }
55 |
56 | [HandlerParameter(true, "0", Min = "-100", Max = "100", Step = "1")]
57 | public double TrimRelativeDeltaAskBidQuantityPercent { get; set; }
58 |
59 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
60 | public ComparisonMode TrimRelativeDeltaAskBidQuantityPercentComparisonMode { get; set; }
61 |
62 | public IList Execute(IBaseTradeStatisticsWithKind tradeStatistics)
63 | {
64 | return Execute(
65 | tradeStatistics,
66 | new TrimContext(UseTrimTradesCount, TrimTradesCount, TrimTradesCountComparisonMode),
67 | new TrimContext(UseTrimQuantity, TrimQuantity, TrimQuantityComparisonMode),
68 | new TrimContext(UseTrimAskQuantity, TrimAskQuantity, TrimAskQuantityComparisonMode),
69 | new TrimContext(UseTrimBidQuantity, TrimBidQuantity, TrimBidQuantityComparisonMode),
70 | new TrimContext(UseTrimDeltaAskBidQuantity, TrimDeltaAskBidQuantity, TrimDeltaAskBidQuantityComparisonMode),
71 | new TrimContext(UseTrimRelativeDeltaAskBidQuantityPercent, TrimRelativeDeltaAskBidQuantityPercent, TrimRelativeDeltaAskBidQuantityPercentComparisonMode));
72 | }
73 |
74 | protected override string GetParametersStateId()
75 | {
76 | return string.Join(
77 | ".",
78 | UseTrimTradesCount,
79 | TrimTradesCount,
80 | TrimTradesCountComparisonMode,
81 | UseTrimQuantity,
82 | TrimQuantity,
83 | TrimQuantityComparisonMode,
84 | UseTrimAskQuantity,
85 | TrimAskQuantity,
86 | TrimAskQuantityComparisonMode,
87 | UseTrimBidQuantity,
88 | TrimBidQuantity,
89 | TrimBidQuantityComparisonMode,
90 | UseTrimDeltaAskBidQuantity,
91 | TrimDeltaAskBidQuantity,
92 | TrimDeltaAskBidQuantityComparisonMode,
93 | UseTrimRelativeDeltaAskBidQuantityPercent,
94 | TrimRelativeDeltaAskBidQuantityPercent,
95 | TrimRelativeDeltaAskBidQuantityPercentComparisonMode);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsSumHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Extended Strings Sum 1", Language = Constants.En)]
12 | [HelperName("Расширенная сумма строк торговой статистики 1", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок 'Расширенная сумма строк торговой статистики 1' выдает значение, основанное на сумме значений строк торговой статистики.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsExtendedBarsSumHandler : TradeStatisticsExtendedBarsHandler, ITradeStatisticsExtendedBarsSumHandler
20 | {
21 | ///
22 | /// \~english Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).
23 | /// \~russian Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).
24 | ///
25 | [HelperName("Kind", Constants.En)]
26 | [HelperName("Вид", Constants.Ru)]
27 | [Description("Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).")]
28 | [HelperDescription("Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).", Constants.En)]
29 | [HandlerParameter(true, nameof(TradeStatisticsKind.TradesCount))]
30 | public TradeStatisticsKind Kind { get; set; }
31 |
32 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
33 | {
34 | return bars.Sum(item => tradeStatistics.GetValue(item, Kind));
35 | }
36 |
37 | protected override string GetParametersStateId()
38 | {
39 | return base.GetParametersStateId() + "." + Kind;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedBarsSumHandler2.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Extended Strings Sum 2", Language = Constants.En)]
12 | [HelperName("Расширенная сумма строк торговой статистики 2", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок 'Расширенная сумма строк торговой статистики 2', выдает значение, основанное на сумме значений строк торговой статистики.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsExtendedBarsSumHandler2 : TradeStatisticsExtendedBarsHandler2, ITradeStatisticsExtendedBarsSumHandler2
20 | {
21 | ///
22 | /// \~english Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).
23 | /// \~russian Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).
24 | ///
25 | [HelperName("Kind", Constants.En)]
26 | [HelperName("Вид", Constants.Ru)]
27 | [Description("Вид торговой статистики (количество сделок, объем торгов, количество покупок, количество продаж, разница количества покупок и продаж, относительная разница количества покупок и продаж).")]
28 | [HelperDescription("Kind of a trade statistics (trades count, trade volume, buy count, sell count, buy and sell difference, relative buy and sell difference).", Constants.En)]
29 | [HandlerParameter(true, nameof(TradeStatisticsKind.TradesCount))]
30 | public TradeStatisticsKind Kind { get; set; }
31 |
32 | protected override double GetResult(IBaseTradeStatisticsWithKind tradeStatistics, IEnumerable bars)
33 | {
34 | return bars.Sum(item => tradeStatistics.GetValue(item, Kind));
35 | }
36 |
37 | protected override string GetParametersStateId()
38 | {
39 | return base.GetParametersStateId() + "." + Kind;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsExtendedExtremumPriceHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using TSLab.Script.Handlers.Options;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | // TODO: английское описание
8 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
9 | [HelperName("Trade Statistics Extended Extremum Price 1", Language = Constants.En)]
10 | [HelperName("Расширенная экстремальная цена торговой статистики 1", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.DOUBLE)]
15 | [Description("Блок 'Расширенная экстремальная цена торговой статистики 1' показывает максимальное значение торговой статистики при экстремальной цене.")]
16 | [HelperDescription("", Constants.En)]
17 | public sealed class TradeStatisticsExtendedExtremumPriceHandler : TradeStatisticsBaseExtendedExtremumPriceHandler, ITradeStatisticsExtendedExtremumPriceHandler
18 | {
19 | [HandlerParameter(true, NotOptimized = true)]
20 | public bool UseTrimTradesCount { get; set; }
21 |
22 | [HandlerParameter(true, "0", Min = "0", Max = "2147483647", Step = "1", EditorMin = "0")]
23 | public int TrimTradesCount { get; set; }
24 |
25 | [HandlerParameter(true, NotOptimized = true)]
26 | public bool UseTrimQuantity { get; set; }
27 |
28 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
29 | public double TrimQuantity { get; set; }
30 |
31 | [HandlerParameter(true, NotOptimized = true)]
32 | public bool UseTrimAskQuantity { get; set; }
33 |
34 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
35 | public double TrimAskQuantity { get; set; }
36 |
37 | [HandlerParameter(true, NotOptimized = true)]
38 | public bool UseTrimBidQuantity { get; set; }
39 |
40 | [HandlerParameter(true, "0", Min = "0", Max = "999999999999999", Step = "1", EditorMin = "0")]
41 | public double TrimBidQuantity { get; set; }
42 |
43 | [HandlerParameter(true, NotOptimized = true)]
44 | public bool UseTrimDeltaAskBidQuantity { get; set; }
45 |
46 | [HandlerParameter(true, "0", Min = "-999999999999999", Max = "999999999999999", Step = "1")]
47 | public double TrimDeltaAskBidQuantity { get; set; }
48 |
49 | [HandlerParameter(true, "false", NotOptimized = true)]
50 | public bool UseTrimRelativeDeltaAskBidQuantityPercent { get; set; }
51 |
52 | [HandlerParameter(true, "0", Min = "-100", Max = "100", Step = "1")]
53 | public double TrimRelativeDeltaAskBidQuantityPercent { get; set; }
54 |
55 | [HandlerParameter(true, nameof(ComparisonMode.GreaterOrEqual))]
56 | public ComparisonMode TrimComparisonMode { get; set; }
57 |
58 | public override IList Execute(IBaseTradeStatisticsWithKind tradeStatistics)
59 | {
60 | return Execute(
61 | tradeStatistics,
62 | new TrimContext(UseTrimTradesCount, TrimTradesCount, TrimComparisonMode),
63 | new TrimContext(UseTrimQuantity, TrimQuantity, TrimComparisonMode),
64 | new TrimContext(UseTrimAskQuantity, TrimAskQuantity, TrimComparisonMode),
65 | new TrimContext(UseTrimBidQuantity, TrimBidQuantity, TrimComparisonMode),
66 | new TrimContext(UseTrimDeltaAskBidQuantity, TrimDeltaAskBidQuantity, TrimComparisonMode),
67 | new TrimContext(UseTrimRelativeDeltaAskBidQuantityPercent, TrimRelativeDeltaAskBidQuantityPercent, TrimComparisonMode));
68 | }
69 |
70 | protected override string GetParametersStateId()
71 | {
72 | return string.Join(
73 | ".",
74 | base.GetParametersStateId(),
75 | UseTrimTradesCount,
76 | TrimTradesCount,
77 | UseTrimQuantity,
78 | TrimQuantity,
79 | UseTrimAskQuantity,
80 | TrimAskQuantity,
81 | UseTrimBidQuantity,
82 | TrimBidQuantity,
83 | UseTrimDeltaAskBidQuantity,
84 | TrimDeltaAskBidQuantity,
85 | UseTrimRelativeDeltaAskBidQuantityPercent,
86 | TrimRelativeDeltaAskBidQuantityPercent,
87 | TrimComparisonMode);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsLowerEdgeHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Lower Edge", Language = Constants.En)]
12 | [HelperName("Нижний уровень торговой статистики", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Кубик 'Нижний уровень торговой статистики' позволяет установить в процентном значении отсечку данных по нижнему уровню. Данный блок соединяется с блоком 'Торговая статистика'.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsLowerEdgeHandler : TradeStatisticsEdgeHandler
20 | {
21 | protected override double GetFirstPrice(IReadOnlyList bars)
22 | {
23 | return bars.First().MinPrice;
24 | }
25 |
26 | protected override double GetLastPrice(IReadOnlyList bars)
27 | {
28 | return bars.Last().MaxPrice;
29 | }
30 |
31 | protected override IEnumerable GetOrderedBars(IEnumerable bars)
32 | {
33 | return bars;
34 | }
35 |
36 | protected override double GetPrice(ITradeHistogramBar bar, double coefficient)
37 | {
38 | double result;
39 | if (coefficient < 0.5)
40 | result = bar.MinPrice + (bar.AveragePrice - bar.MinPrice) * coefficient * 2;
41 | else if (coefficient > 0.5)
42 | result = bar.AveragePrice + (bar.MaxPrice - bar.AveragePrice) * (coefficient - 0.5) * 2;
43 | else
44 | result = bar.AveragePrice;
45 |
46 | return result;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ClusterAnalysis/TradeStatisticsUpperEdgeHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | // TODO: английское описание
10 | [HandlerCategory(HandlerCategories.ClusterAnalysis)]
11 | [HelperName("Trade Statistics Upper Edge", Language = Constants.En)]
12 | [HelperName("Верхний уровень торговой статистики", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.TRADE_STATISTICS | TemplateTypes.LAST_CONTRACTS_TRADE_STATISTICS)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок 'Верхний уровень торговой статистики' позволяет установить в процентном значении отсечки данных по верхнему уровню. Данный блок соединяется с блоком 'Торговая статистика'.")]
18 | [HelperDescription("", Constants.En)]
19 | public sealed class TradeStatisticsUpperEdgeHandler : TradeStatisticsEdgeHandler
20 | {
21 | protected override double GetFirstPrice(IReadOnlyList bars)
22 | {
23 | return bars.Last().MaxPrice;
24 | }
25 |
26 | protected override double GetLastPrice(IReadOnlyList bars)
27 | {
28 | return bars.First().MinPrice;
29 | }
30 |
31 | protected override IEnumerable GetOrderedBars(IEnumerable bars)
32 | {
33 | return bars.Reverse();
34 | }
35 |
36 | protected override double GetPrice(ITradeHistogramBar bar, double coefficient)
37 | {
38 | double result;
39 | if (coefficient < 0.5)
40 | result = bar.MaxPrice + (bar.AveragePrice - bar.MaxPrice) * coefficient * 2;
41 | else if (coefficient > 0.5)
42 | result = bar.AveragePrice + (bar.MinPrice - bar.AveragePrice) * (coefficient - 0.5) * 2;
43 | else
44 | result = bar.AveragePrice;
45 |
46 | return result;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ConstList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | internal sealed class ConstList : IList, IReadOnlyList
8 | {
9 | private static readonly IEqualityComparer s_equalityComparer = EqualityComparer.Default;
10 | private readonly T m_value;
11 |
12 | public ConstList(int count, T value)
13 | {
14 | if (count < 0)
15 | throw new ArgumentOutOfRangeException(nameof(count));
16 |
17 | Count = count;
18 | m_value = value;
19 | }
20 |
21 | public IEnumerator GetEnumerator()
22 | {
23 | for (var i = 0; i < Count; i++)
24 | yield return m_value;
25 | }
26 |
27 | IEnumerator IEnumerable.GetEnumerator()
28 | {
29 | return GetEnumerator();
30 | }
31 |
32 | public void Add(T item)
33 | {
34 | throw new NotSupportedException();
35 | }
36 |
37 | public void Clear()
38 | {
39 | throw new NotSupportedException();
40 | }
41 |
42 | public bool Contains(T item)
43 | {
44 | return Count > 0 && s_equalityComparer.Equals(m_value, item);
45 | }
46 |
47 | public void CopyTo(T[] array, int arrayIndex)
48 | {
49 | throw new NotSupportedException();
50 | }
51 |
52 | public bool Remove(T item)
53 | {
54 | throw new NotSupportedException();
55 | }
56 |
57 | public int Count { get; }
58 |
59 | public bool IsReadOnly => true;
60 |
61 | public int IndexOf(T item)
62 | {
63 | return Contains(item) ? 0 : -1;
64 | }
65 |
66 | public void Insert(int index, T item)
67 | {
68 | throw new NotSupportedException();
69 | }
70 |
71 | public void RemoveAt(int index)
72 | {
73 | throw new NotSupportedException();
74 | }
75 |
76 | public T this[int index]
77 | {
78 | get
79 | {
80 | if (index < 0 || index >= Count)
81 | throw new ArgumentOutOfRangeException(nameof(index));
82 |
83 | return m_value;
84 | }
85 | set { throw new NotSupportedException(); }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Cycle/AddPositionHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using TSLab.Script.Handlers;
5 |
6 | namespace TSLab.ScriptEngine.Template
7 | {
8 | [HandlerInvisible]
9 | [OutputsCount(0)]
10 | public sealed class AddPositionHandler : IHandler
11 | {
12 | [HandlerParameter(true, "false", NotOptimized = true)]
13 | public bool UseVirtualClosing { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Cycle/CycleBoolHandler.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | [HandlerInvisible]
4 | [OutputType(TemplateTypes.BOOL)]
5 | public abstract class CycleBoolHandler : IValuesHandlerWithNumber, IOneSourceHandler, IBooleanInputs, IBooleanReturns
6 | {
7 | private int m_barIndex = -1;
8 | private bool m_result;
9 | private bool m_value;
10 |
11 | public bool Execute(bool value, int barIndex)
12 | {
13 | if (m_barIndex != barIndex)
14 | {
15 | m_barIndex = barIndex;
16 | m_result = m_value;
17 | m_value = value;
18 | }
19 | else
20 | m_value = Execute(m_value, value);
21 |
22 | return m_result;
23 | }
24 |
25 | protected abstract bool Execute(bool value1, bool value2);
26 | }
27 |
28 | public sealed class CycleAndHandler : CycleBoolHandler
29 | {
30 | protected override bool Execute(bool value1, bool value2) => value1 && value2;
31 | }
32 |
33 | public sealed class CycleOrHandler : CycleBoolHandler
34 | {
35 | protected override bool Execute(bool value1, bool value2) => value1 || value2;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Cycle/CycleHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace TSLab.Script.Handlers
4 | {
5 | [HandlerInvisible]
6 | [OutputType(TemplateTypes.INT)]
7 | public sealed class CycleHandler : IHandler
8 | {
9 | [HandlerParameter(true, "1", Min = "1", Max = "2147483647", Step = "1", EditorMin = "1", EditorMax = "2147483647")]
10 | public int MaxCount { get; set; }
11 |
12 | public int GetCount(double value)
13 | {
14 | if (double.IsNaN(value))
15 | return 0;
16 |
17 | if (value <= int.MinValue)
18 | return int.MinValue;
19 |
20 | if (value >= int.MaxValue)
21 | return int.MaxValue;
22 |
23 | return GetCount((int)Math.Round(value, MidpointRounding.AwayFromZero));
24 | }
25 |
26 | public int GetCount(int value)
27 | {
28 | return Math.Min(MaxCount, value);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Cycle/CycleResultHandler.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | [HandlerInvisible]
4 | public abstract class CycleResultHandler : IHandler
5 | {
6 | [HandlerParameter(true, "0", Min = "0", Max = "2147483647", Step = "1", EditorMin = "0", EditorMax = "2147483647")]
7 | public int Index { get; set; }
8 |
9 | [HandlerParameter(true, "true")]
10 | public bool UseLastIndex { get; set; }
11 | }
12 |
13 | [OutputType(TemplateTypes.BOOL)]
14 | public sealed class CycleBoolResultHandler : CycleResultHandler
15 | {
16 | }
17 |
18 | [OutputType(TemplateTypes.DOUBLE)]
19 | public sealed class CycleDoubleResultHandler : CycleResultHandler
20 | {
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Cycle/CycleResultsHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | [HandlerInvisible]
8 | public abstract class CycleResultsHandler : IValuesHandlerWithNumber, IOneSourceHandler, IContextUses
9 | {
10 | private sealed class ExReadOnlyList : IList, IReadOnlyList
11 | {
12 | private readonly IReadOnlyList m_src;
13 |
14 | public ExReadOnlyList(IReadOnlyList src)
15 | {
16 | m_src = src;
17 | }
18 |
19 | public IEnumerator GetEnumerator()
20 | {
21 | return m_src.GetEnumerator();
22 | }
23 |
24 | IEnumerator IEnumerable.GetEnumerator()
25 | {
26 | return GetEnumerator();
27 | }
28 |
29 | public void Add(T item)
30 | {
31 | throw new NotSupportedException();
32 | }
33 |
34 | public void Clear()
35 | {
36 | throw new NotSupportedException();
37 | }
38 |
39 | public bool Contains(T item)
40 | {
41 | throw new NotSupportedException();
42 | }
43 |
44 | public void CopyTo(T[] array, int arrayIndex)
45 | {
46 | throw new NotSupportedException();
47 | }
48 |
49 | public bool Remove(T item)
50 | {
51 | throw new NotSupportedException();
52 | }
53 |
54 | public int Count => m_src.Count;
55 |
56 | public bool IsReadOnly => true;
57 |
58 | public int IndexOf(T item)
59 | {
60 | throw new NotSupportedException();
61 | }
62 |
63 | public void Insert(int index, T item)
64 | {
65 | throw new NotSupportedException();
66 | }
67 |
68 | public void RemoveAt(int index)
69 | {
70 | throw new NotSupportedException();
71 | }
72 |
73 | public T this[int index]
74 | {
75 | get => index < Count ? m_src[index] : default(T);
76 | set => throw new NotSupportedException();
77 | }
78 | }
79 |
80 | private readonly List> m_listOfLists = new List>();
81 | private readonly List m_list = new List();
82 | private IContext m_context;
83 |
84 | public IContext Context
85 | {
86 | get => m_context;
87 | set
88 | {
89 | m_context = value;
90 | m_list.Capacity = value.BarsCount;
91 | }
92 | }
93 |
94 | public IReadOnlyList> Execute(T value, int barIndex)
95 | {
96 | if (m_listOfLists.Count == barIndex)
97 | {
98 | if (barIndex > 0)
99 | m_listOfLists[barIndex - 1] = new ExReadOnlyList(m_list.ToArray());
100 |
101 | m_list.Clear();
102 | m_listOfLists.Add(m_list);
103 | }
104 | m_list.Add(value);
105 | return m_listOfLists;
106 | }
107 | }
108 |
109 | [OutputType(TemplateTypes.BOOL | TemplateTypes.LIST_OF_LISTS)]
110 | public sealed class CycleBoolResultsHandler : CycleResultsHandler, IBooleanInputs
111 | {
112 | }
113 |
114 | [OutputType(TemplateTypes.DOUBLE | TemplateTypes.LIST_OF_LISTS)]
115 | public sealed class CycleDoubleResultsHandler : CycleResultsHandler, IDoubleInputs
116 | {
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Cycle/CycleValueUpdaterHandler.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | [HandlerInvisible]
4 | [OutputType(TemplateTypes.DOUBLE)]
5 | public sealed class CycleValueUpdaterHandler : IHandler
6 | {
7 | [HandlerParameter(false, "0", NotOptimized = true)]
8 | public double StartFrom { get; set; }
9 |
10 | [HandlerParameter(false, nameof(ValueUpdaterExecutionOrder.AtTheEnd), NotOptimized = true)]
11 | public ValueUpdaterExecutionOrder ExecutionOrder { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GraphPane/InteractiveLineGen.BaseList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed partial class InteractiveLineGen
8 | {
9 | private abstract class BaseList : IList
10 | {
11 | protected BaseList(int count)
12 | : this(count, 0, count - 1)
13 | {
14 | }
15 |
16 | protected BaseList(int count, int minIndex, int maxIndex)
17 | {
18 | if (count == 0)
19 | {
20 | if (minIndex != -1)
21 | throw new ArgumentOutOfRangeException(nameof(minIndex));
22 |
23 | if (maxIndex != -1)
24 | throw new ArgumentOutOfRangeException(nameof(maxIndex));
25 | }
26 | else if (count > 0)
27 | {
28 | if (minIndex < 0)
29 | throw new ArgumentOutOfRangeException(nameof(minIndex));
30 |
31 | if (maxIndex >= count)
32 | throw new ArgumentOutOfRangeException(nameof(maxIndex));
33 |
34 | if (minIndex > maxIndex)
35 | throw new ArgumentOutOfRangeException(nameof(maxIndex));
36 | }
37 | else
38 | throw new ArgumentOutOfRangeException(nameof(count));
39 |
40 | Count = count;
41 | MinIndex = minIndex;
42 | MaxIndex = maxIndex;
43 | }
44 |
45 | public IEnumerator GetEnumerator()
46 | {
47 | if (Count > 0)
48 | {
49 | for (var i = 0; i < MinIndex; i++)
50 | yield return double.NaN;
51 |
52 | for (var i = MinIndex; i <= MaxIndex; i++)
53 | yield return GetValue(i);
54 |
55 | for (var i = MaxIndex + 1; i < Count; i++)
56 | yield return double.NaN;
57 | }
58 | else
59 | yield return double.NaN;
60 | }
61 |
62 | IEnumerator IEnumerable.GetEnumerator()
63 | {
64 | return GetEnumerator();
65 | }
66 |
67 | public void Add(double item)
68 | {
69 | throw new NotSupportedException();
70 | }
71 |
72 | public void Clear()
73 | {
74 | throw new NotSupportedException();
75 | }
76 |
77 | public bool Contains(double item)
78 | {
79 | return IndexOf(item) >= 0;
80 | }
81 |
82 | public void CopyTo(double[] array, int arrayIndex)
83 | {
84 | throw new NotSupportedException();
85 | }
86 |
87 | public bool Remove(double item)
88 | {
89 | throw new NotSupportedException();
90 | }
91 |
92 | public int Count { get; }
93 |
94 | public bool IsReadOnly
95 | {
96 | get { return true; }
97 | }
98 |
99 | public abstract int IndexOf(double item);
100 |
101 | public void Insert(int index, double item)
102 | {
103 | throw new NotSupportedException();
104 | }
105 |
106 | public void RemoveAt(int index)
107 | {
108 | throw new NotSupportedException();
109 | }
110 |
111 | public double this[int index]
112 | {
113 | get { return index >= MinIndex && index <= MaxIndex ? GetValue(index) : double.NaN; }
114 | set { throw new NotSupportedException(); }
115 | }
116 |
117 | protected int MinIndex { get; }
118 |
119 | protected int MaxIndex { get; }
120 |
121 | protected abstract double GetValue(int index);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/GraphPane/InteractiveLineGen.ConstList.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | public sealed partial class InteractiveLineGen
4 | {
5 | private sealed class ConstList : BaseList
6 | {
7 | private readonly double m_value;
8 |
9 | public ConstList(double value, int count)
10 | : base(count)
11 | {
12 | m_value = value;
13 | }
14 |
15 | public ConstList(double value, int count, int minIndex, int maxIndex)
16 | : base(count, minIndex, maxIndex)
17 | {
18 | m_value = value;
19 | }
20 |
21 | public override int IndexOf(double item)
22 | {
23 | return m_value == item ? MinIndex : -1;
24 | }
25 |
26 | protected override double GetValue(int index)
27 | {
28 | return m_value;
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/GraphPane/InteractiveLineGen.LineList.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | public sealed partial class InteractiveLineGen
4 | {
5 | private sealed class LineList : BaseList
6 | {
7 | private readonly double m_a;
8 | private readonly double m_b;
9 |
10 | public LineList(double a, double b, int count, int minIndex, int maxIndex)
11 | : base(count, minIndex, maxIndex)
12 | {
13 | m_a = a;
14 | m_b = b;
15 | }
16 |
17 | public override int IndexOf(double item)
18 | {
19 | var minValue = GetValue(MinIndex);
20 | var maxValue = GetValue(MaxIndex);
21 |
22 | if (minValue > maxValue)
23 | {
24 | var value = minValue;
25 | minValue = maxValue;
26 | maxValue = value;
27 | }
28 | if (item >= minValue && item <= maxValue)
29 | for (var i = MinIndex; i <= MaxIndex; i++)
30 | if (GetValue(i) == item)
31 | return i;
32 |
33 | return -1;
34 | }
35 |
36 | protected override double GetValue(int index)
37 | {
38 | return m_a * index + m_b;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/HelperDescriptionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace TSLab.Script.Handlers.Options
5 | {
6 | ///
7 | /// Описание кубика как его будет видеть Пользователь.
8 | /// Это вспомогательный атрибут для упрощения локализации зоопарка кубиков (как опционных, так и обычных).
9 | ///
10 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
11 | public class HelperDescriptionAttribute : Attribute
12 | {
13 | public HelperDescriptionAttribute()
14 | : this(String.Empty, Constants.Ru)
15 | {
16 | }
17 |
18 | public HelperDescriptionAttribute(string description)
19 | : this(description, Constants.Ru)
20 | {
21 | }
22 |
23 | public HelperDescriptionAttribute(string description, string language)
24 | {
25 | Description = description ?? String.Empty;
26 | Language = String.IsNullOrWhiteSpace(language) ? Constants.Ru : language;
27 | }
28 |
29 | public string Description { get; set; }
30 |
31 | public string Language { get; set; }
32 |
33 | public override string ToString()
34 | {
35 | return Description;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/HelperLinkAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace TSLab.Script.Handlers.Options
5 | {
6 | ///
7 | /// Ссылка на скрипт или статью с использованием данного кубика.
8 | /// Это вспомогательный атрибут для упрощения локализации зоопарка кубиков (как опционных, так и обычных),
9 | /// а также для автоматизированного формирования документации.
10 | ///
11 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
12 | public class HelperLinkAttribute : Attribute
13 | {
14 | public HelperLinkAttribute(string link)
15 | : this(link, link, Constants.Ru)
16 | {
17 | }
18 |
19 | public HelperLinkAttribute(string link, string name, string language)
20 | {
21 | Link = link ?? String.Empty;
22 | Name = name ?? String.Empty;
23 | Language = String.IsNullOrWhiteSpace(language) ? Constants.Ru : language;
24 | }
25 |
26 | public string Link { get; set; }
27 |
28 | public string Name { get; set; }
29 |
30 | public string Language { get; set; }
31 |
32 | public override string ToString()
33 | {
34 | return Name + ": " + Link;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/HelperNameAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace TSLab.Script.Handlers.Options
5 | {
6 | ///
7 | /// Название кубика как его будет видеть Пользователь.
8 | /// Вспомогательный атрибут для упрощения локализации зоопарка кубиков (как опционных, так и обычных),
9 | /// а также для автоматизированного формирования документации.
10 | ///
11 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
12 | public class HelperNameAttribute : Attribute
13 | {
14 | public HelperNameAttribute(string name)
15 | : this(name, Constants.Ru)
16 | {
17 | }
18 |
19 | public HelperNameAttribute(string name, string language)
20 | {
21 | Name = name ?? String.Empty;
22 | Language = String.IsNullOrWhiteSpace(language) ? Constants.Ru : language;
23 | }
24 |
25 | public string Name { get; set; }
26 |
27 | public string Language { get; set; }
28 |
29 | public override string ToString()
30 | {
31 | return Name;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Indicators/AMA.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | // ReSharper disable InconsistentNaming
8 | namespace TSLab.Script.Handlers
9 | {
10 | [HandlerCategory(HandlerCategories.Indicators)]
11 | [HelperName("AMA", Language = Constants.En)]
12 | [HelperName("AMA", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.DOUBLE)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Адаптивное сглаженное скользящее среднее.")]
18 | [HelperDescription("The Adaptive Moving Average.", Constants.En)]
19 | public sealed class AMA : DoubleStreamAndValuesHandlerWithPeriod
20 | {
21 | private ShrinkedList m_source;
22 | private double m_lastResult;
23 |
24 | public override bool IsGapTolerant
25 | {
26 | get { return false; }
27 | }
28 |
29 | public override IList Execute(IList source)
30 | {
31 | return Calc(source, Period, Context);
32 | }
33 |
34 | protected override void InitExecuteContext()
35 | {
36 | m_source = new ShrinkedList(Period + 2);
37 | m_lastResult = 0;
38 | }
39 |
40 | protected override void ClearExecuteContext()
41 | {
42 | m_source = null;
43 | m_lastResult = 0;
44 | }
45 |
46 | protected override void InitForGap()
47 | {
48 | var firstIndex = Math.Max(m_executeContext.LastIndex + 1, m_executeContext.Index - 7 * Period);
49 | for (var i = firstIndex; i < m_executeContext.Index; i++)
50 | {
51 | m_source.Add(m_executeContext.GetSourceForGap(i));
52 | m_lastResult = Calc(m_source, m_lastResult, m_source.Count - 1, Period);
53 | }
54 | }
55 |
56 | protected override double Execute()
57 | {
58 | m_source.Add(m_executeContext.Source);
59 | m_lastResult = Calc(m_source, m_lastResult, m_source.Count - 1, Period);
60 | return m_lastResult;
61 | }
62 |
63 | public static IList Calc(IList source, int period, IMemoryContext context = null)
64 | {
65 | if (source == null)
66 | throw new ArgumentNullException(nameof(source));
67 |
68 | if (period <= 0)
69 | throw new ArgumentOutOfRangeException(nameof(period));
70 |
71 | var result = context?.GetArray(source.Count) ?? new double[source.Count];
72 | if (result.Length > 0)
73 | {
74 | result[0] = Calc(source, 0, 0, period);
75 | for (var i = 1; i < result.Length; i++)
76 | result[i] = Calc(source, result[i - 1], i, period);
77 | }
78 | return result;
79 | }
80 |
81 | private static double Calc(IList source, double lastResult, int index, int period)
82 | {
83 | if (index <= period)
84 | return source[index];
85 |
86 | var signal = Math.Abs(source[index] - source[index - period]);
87 | var noise = 0.000000001;
88 |
89 | for (var i = 0; i < period; i++)
90 | noise = noise + Math.Abs(source[index - i] - source[index - i - 1]);
91 |
92 | var er = signal / noise;
93 | var ssc = (er * 0.60215) + 0.06452;
94 | var cst = Math.Pow(ssc, 2);
95 | var result = lastResult + cst * (source[index] - lastResult);
96 | return result;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Indicators/BarsCountForValuesSumHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Utils;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.Indicators)]
10 | [HelperName("Bars count for values sum", Language = Constants.En)]
11 | [HelperName("Количество баров для суммы значений", Language = Constants.Ru)]
12 | [Description("Количество баров для суммы значений")]
13 | [HelperDescription("Bars count for values sum", Constants.En)]
14 | public sealed class BarsCountForValuesSumHandler : DoubleStreamAndValuesHandler
15 | {
16 | private double[] m_source;
17 |
18 | public override bool IsGapTolerant => false;
19 |
20 | ///
21 | /// \~english Indicator values sum
22 | /// \~russian Сумма значений индикатора
23 | ///
24 | [HelperName("Values sum", Constants.En)]
25 | [HelperName("Сумма значений", Constants.Ru)]
26 | [Description("Сумма значений индикатора")]
27 | [HelperDescription("Indicator values sum", Constants.En)]
28 | [HandlerParameter(true, "1", Min = "0", Max = "2147483647", Step = "1", EditorMin = "1")]
29 | public double ValuesSum { get; set; }
30 |
31 | public override IList Execute(IList source)
32 | {
33 | if (source == null)
34 | throw new ArgumentNullException(nameof(source));
35 |
36 | if (source.Count == 0)
37 | return EmptyArrays.Double;
38 |
39 | var results = Context.GetArray(source.Count);
40 | for (var i = 0; i < source.Count; i++)
41 | results[i] = Calculate(source, i);
42 |
43 | return results;
44 | }
45 |
46 | protected override void InitExecuteContext()
47 | {
48 | m_source = Context.GetArray(Context.BarsCount);
49 | }
50 |
51 | protected override void ClearExecuteContext()
52 | {
53 | Context.ReleaseArray(m_source);
54 | m_source = null;
55 | }
56 |
57 | protected override void InitForGap()
58 | {
59 | for (var i = m_executeContext.LastIndex; i < m_executeContext.Index; i++)
60 | m_source[i] = m_executeContext.GetSourceForGap(i);
61 | }
62 |
63 | protected override double Execute()
64 | {
65 | var index = m_executeContext.Index;
66 | m_source[index] = m_executeContext.Source;
67 | return Calculate(m_source, index);
68 | }
69 |
70 | private double Calculate(IList source, int index)
71 | {
72 | var valuesSum = 0D;
73 | for (var j = index; j >= 0; j--)
74 | {
75 | valuesSum += source[j];
76 | if (valuesSum >= ValuesSum)
77 | return index - j + 1;
78 | }
79 | return 0;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Indicators/DoubleStreamAndValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 |
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | public abstract class DoubleStreamAndValuesHandler : IDoubleStreamAndValuesHandler
10 | {
11 | protected sealed class ExecuteContext
12 | {
13 | private double m_a;
14 | private double m_b;
15 |
16 | public double Source { get; set; }
17 | public int Index { get; set; }
18 | public double LastResult { get; set; }
19 | public double LastSource { get; set; }
20 | public int LastIndex { get; set; }
21 |
22 | public void InitForGap()
23 | {
24 | if (LastIndex < 0)
25 | {
26 | m_a = 0;
27 | m_b = Source;
28 | }
29 | else
30 | {
31 | m_a = (LastSource - Source) / (LastIndex - Index);
32 | m_b = LastSource - m_a * LastIndex;
33 | }
34 | }
35 |
36 | public double GetSourceForGap(int i)
37 | {
38 | var source = m_a * i + m_b;
39 | return source;
40 | }
41 | }
42 |
43 | protected ExecuteContext m_executeContext;
44 |
45 | public IContext Context { get; set; }
46 |
47 | public abstract bool IsGapTolerant { get; }
48 |
49 | public abstract IList Execute(IList source);
50 |
51 | public double Execute(double source, int index)
52 | {
53 | if (index < 0 || index >= Context.BarsCount)
54 | throw new ArgumentOutOfRangeException(nameof(index));
55 |
56 | if (m_executeContext != null)
57 | {
58 | if (index < m_executeContext.LastIndex)
59 | throw new ArgumentException(nameof(index));
60 |
61 | if (index == m_executeContext.LastIndex)
62 | return m_executeContext.LastResult;
63 |
64 | m_executeContext.Source = source;
65 | m_executeContext.Index = index;
66 | }
67 | else
68 | {
69 | m_executeContext = new ExecuteContext { Source = source, Index = index, LastIndex = -1 };
70 | InitExecuteContext();
71 | }
72 | if (index - m_executeContext.LastIndex > 1)
73 | {
74 | m_executeContext.InitForGap();
75 | InitForGap();
76 | }
77 | m_executeContext.LastResult = Execute();
78 | m_executeContext.LastSource = source;
79 | m_executeContext.LastIndex = index;
80 |
81 | if (index == Context.BarsCount - 1)
82 | ClearExecuteContext();
83 |
84 | return m_executeContext.LastResult;
85 | }
86 |
87 | protected abstract void InitExecuteContext();
88 |
89 | protected abstract void ClearExecuteContext();
90 |
91 | protected abstract void InitForGap();
92 |
93 | protected abstract double Execute();
94 | }
95 |
96 | public abstract class DoubleStreamAndValuesHandlerWithPeriod : DoubleStreamAndValuesHandler, IDoubleStreamAndValuesHandlerWithPeriod
97 | {
98 | protected const int GapTolerancePeriodMultiplier = 2;
99 | private int m_period = 1;
100 |
101 | ///
102 | /// \~english Indicator period (processing window)
103 | /// \~russian Период индикатора (окно расчетов)
104 | ///
105 | [HelperName("Period", Constants.En)]
106 | [HelperName("Период", Constants.Ru)]
107 | [Description("Период индикатора (окно расчетов)")]
108 | [HelperDescription("Indicator period (processing window)", Constants.En)]
109 | [HandlerParameter(true, "20", Min = "10", Max = "100", Step = "5", EditorMin = "1")]
110 | public int Period
111 | {
112 | get { return m_period; }
113 | set { m_period = Math.Max(value, 1); }
114 | }
115 |
116 | protected virtual bool IsSimple
117 | {
118 | get { return Period == 1 || Context.BarsCount == 1; }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Indicators/SomeIndicators.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Globalization;
6 |
7 | using TSLab.Script.Handlers.Options;
8 | using TSLab.Script.Helpers;
9 |
10 | // ReSharper disable UnusedMember.Global
11 | // ReSharper disable MemberCanBePrivate.Global
12 | // ReSharper disable UnusedAutoPropertyAccessor.Global
13 | // ReSharper disable ClassNeverInstantiated.Global
14 | // ReSharper disable InconsistentNaming
15 | // ReSharper disable CompareOfFloatsByEqualityOperator
16 | namespace TSLab.Script.Handlers
17 | {
18 | [HandlerCategory(HandlerCategories.Indicators)]
19 | [HelperName("StochK", Language = Constants.En)]
20 | [HelperName("StochK", Language = Constants.Ru)]
21 | #region Атрибуты с описанием и ссылками
22 | [InputsCount(1)]
23 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
24 | [OutputsCount(1)]
25 | [OutputType(TemplateTypes.DOUBLE)]
26 | [Description("Стохастический осциллятор (Stochastic Oscillator) = (Цена закрытия текущего бара - Минимальное значение за период от минимума бара) / (Максимальное значение за период от максимума бара - Минимальное значение за период от минимума бара) * 100. " +
27 | "Стохастический осциллятор измеряет насколько цена близка к своим верхним или нижним границам. Индикатор изменяется в диапазоне от 0 до 100.")]
28 | [HelperDescription("The Stochastic Oscillator = (Current bar closing price - Period minimum value calculated on bar minimum) / (Bar maximum value calculated on bar maximum - Bar minimum value based on bar minimum) * 100. " +
29 | "This indicator shows how close price is to its upper and lower borders.The indicator varies in the range from 0 to 100.", Constants.En)]
30 | [HelperLink(@"http://www.tslab.ru/files/script/StochK.xml", "Пример по индикатору Stochastic K", Constants.Ru)]
31 | [HelperLink(@"http://www.tslab.ru/files/script/StochK.xml", "Example of Stochastic K", Constants.En)]
32 | #endregion Атрибуты с описанием и ссылками
33 | public sealed class StochK : BasePeriodIndicatorHandler, IBar2DoubleHandler, IContextUses
34 | {
35 | public IList Execute(ISecurity source)
36 | {
37 | var high = Context.GetData("Highest", new[] { Period.ToString(CultureInfo.InvariantCulture), source.CacheName },
38 | () => Series.Highest(source.GetHighPrices(Context).AsReadOnly(), Period));
39 | var low = Context.GetData("Lowest", new[] { Period.ToString(CultureInfo.InvariantCulture), source.CacheName },
40 | () => Series.Lowest(source.GetLowPrices(Context).AsReadOnly(), Period));
41 | var bars = source.Bars;
42 | var list = Context?.GetArray(bars.Count) ?? new double[bars.Count];
43 | for (int i = 0; i < bars.Count; i++)
44 | {
45 | var hl = high[i] - low[i];
46 | var stochK = hl == 0 ? 0 : 100 * (bars[i].Close - low[i]) / hl;
47 | list[i] = stochK;
48 | }
49 | return list;
50 | }
51 |
52 | public IContext Context { get; set; }
53 | }
54 |
55 | [HandlerCategory(HandlerCategories.Indicators)]
56 | //[HandlerName("StochRSI")]
57 | [HelperName("Stoch RSI", Language = Constants.En)]
58 | [HelperName("Stoch RSI", Language = Constants.Ru)]
59 | [InputsCount(1)]
60 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
61 | [OutputsCount(1)]
62 | [OutputType(TemplateTypes.DOUBLE)]
63 | [Description("Стохастик от индекса относительной силы. StochRSI = (Текущее значение RSI - Минимальное значение RSI за период) / (Максимальное значение RSI за период - Минимальное значение RSI за период) * 100.")]
64 | [HelperDescription("Stochastics based on relative strength index. StochRSI = (Current RSI - period minimum RSI) / (Period maximum RSI - period minimum RSI) * 100.", Constants.En)]
65 | [SuppressMessage("StyleCopPlus.StyleCopPlusRules", "SP0100:AdvancedNamingRules", Justification = "Reviewed. Suppression is OK here.")]
66 | public sealed class StochRSI : BasePeriodIndicatorHandler, IBar2DoubleHandler, IContextUses
67 | {
68 | public IList Execute(ISecurity source)
69 | {
70 | var rsi = Context.GetData("RSI", new[] { Period.ToString(CultureInfo.InvariantCulture), source.CacheName },
71 | () => Series.RSI(source.GetClosePrices(Context).AsReadOnly(), Period));
72 | var high = Series.Highest(rsi.AsReadOnly(), Period, Context);
73 | var low = Series.Lowest(rsi.AsReadOnly(), Period, Context);
74 | var list = Context?.GetArray(rsi.Count) ?? new double[rsi.Count];
75 | for (int i = 0; i < rsi.Count; i++)
76 | {
77 | var hl = high[i] - low[i];
78 | var stochRSI = hl == 0 ? 0 : 100 * (rsi[i] - low[i]) / hl;
79 | list[i] = stochRSI;
80 | }
81 | Context?.ReleaseArray((Array)high);
82 | Context?.ReleaseArray((Array)low);
83 | return list;
84 | }
85 |
86 | public IContext Context { get; set; }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Indicators/SumForTimeFrameHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.DataSource;
6 | using TSLab.Script.Handlers.Options;
7 |
8 | namespace TSLab.Script.Handlers
9 | {
10 | // TODO: у этого кубика нет описания. Судя по коду что-то вроде "сумма значений в пределах указанного таймфрейма"
11 | [HandlerCategory(HandlerCategories.Indicators)]
12 | [HelperName("Sum for time frame", Language = Constants.En)]
13 | [HelperName("Сумма за таймфрейм", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.DOUBLE)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.DOUBLE)]
18 | [Description("Сумма за таймфрейм")]
19 | [HelperDescription("Sum for time frame", Constants.En)]
20 | public sealed class SumForTimeFrameHandler : IDoubleStreamAndValuesHandler
21 | {
22 | public IContext Context { get; set; }
23 |
24 | public bool IsGapTolerant => true;
25 |
26 | ///
27 | /// \~english Timeframe (format D.HH:MM:SS)
28 | /// \~russian Интервал (формат Д.ЧЧ:ММ:СС)
29 | ///
30 | [HelperName("Timeframe", Constants.En)]
31 | [HelperName("Интервал", Constants.Ru)]
32 | [Description("Интервал (формат Д.ЧЧ:ММ:СС)")]
33 | [HelperDescription("Timeframe (format D.HH:MM:SS)", Constants.En)]
34 | [HandlerParameter(true, "1:0:0", Min = "0:0:0", Max = "365.0:0:0", Step = "0:1:0", EditorMin = "0:0:0", EditorMax = "365.0:0:0")]
35 | public TimeSpan TimeFrame { get; set; }
36 |
37 | private DateTime m_firstDateTime;
38 | private DateTime m_lastDateTime;
39 | private double m_sum;
40 | private int m_index = -1;
41 |
42 | public IList Execute(IList values)
43 | {
44 | var security = Context.Runtime.Securities.First();
45 | var bars = security.Bars;
46 | var count = Math.Min(bars.Count, values.Count);
47 |
48 | if (count == 0)
49 | return new ConstList(values.Count, 0);
50 |
51 | var results = Context?.GetArray(values.Count) ?? new double[values.Count];
52 | TimeFrameUtils.GetFirstBounds(TimeFrame, bars[0].Date, out var firstDateTime, out var lastDateTime);
53 | var sum = 0D;
54 |
55 | for (var i = 0; i < count; i++)
56 | {
57 | var barDate = bars[i].Date;
58 | if (barDate >= lastDateTime)
59 | {
60 | TimeFrameUtils.GetBounds(TimeFrame, barDate, ref firstDateTime, ref lastDateTime);
61 | sum = 0;
62 | }
63 | results[i] = sum += values[i];
64 | }
65 | for (var i = count; i < results.Length; i++)
66 | results[i] = sum;
67 |
68 | return results;
69 | }
70 |
71 | public double Execute(double value, int index)
72 | {
73 | if (index < m_index)
74 | throw new InvalidOperationException();
75 |
76 | if (index == m_index)
77 | return m_sum;
78 |
79 | var security = Context.Runtime.Securities.First();
80 | var bars = security.Bars;
81 | var count = Math.Min(bars.Count, index + 1);
82 |
83 | if (count == 0)
84 | return 0;
85 |
86 | if (m_firstDateTime == default(DateTime))
87 | TimeFrameUtils.GetFirstBounds(TimeFrame, bars[index].Date, out m_firstDateTime, out m_lastDateTime);
88 |
89 | for (var i = m_index + 1; i < count; i++)
90 | {
91 | var barDate = bars[i].Date;
92 | if (barDate >= m_lastDateTime)
93 | {
94 | TimeFrameUtils.GetBounds(TimeFrame, barDate, ref m_firstDateTime, ref m_lastDateTime);
95 | m_sum = 0;
96 | }
97 | m_sum += value;
98 | }
99 | m_index = index;
100 | return m_sum;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Indicators/Trix.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 |
5 | using TSLab.Script.Handlers.Options;
6 | using TSLab.Script.Helpers;
7 |
8 | // ReSharper disable InconsistentNaming
9 | namespace TSLab.Script.Handlers
10 | {
11 | [HandlerCategory(HandlerCategories.Indicators)]
12 | [HelperName("TRIX", Language = Constants.En)]
13 | [HelperName("TRIX", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.DOUBLE)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.DOUBLE)]
18 | [Description("Тройное экспоненциальное скользящее.")]
19 | [HelperDescription("The Triple Exponential Average.", Constants.En)]
20 | public sealed class TRIX : DoubleStreamAndValuesHandlerWithPeriod
21 | {
22 | private double m_lastEma3;
23 | private EMA m_ema1;
24 | private EMA m_ema2;
25 | private EMA m_ema3;
26 |
27 | public override bool IsGapTolerant
28 | {
29 | get { return IsSimple; }
30 | }
31 |
32 | public override IList Execute(IList source)
33 | {
34 | if (source == null)
35 | throw new ArgumentNullException(nameof(source));
36 |
37 | IList ema3;
38 | if (IsSimple)
39 | ema3 = source;
40 | else
41 | {
42 | var ema1 = Series.EMA(source.AsReadOnly(), Period, Context);
43 | var ema2 = Series.EMA(ema1.AsReadOnly(), Period, Context);
44 | Context?.ReleaseArray((Array)ema1);
45 | ema3 = Series.EMA(ema2.AsReadOnly(), Period, Context);
46 | Context?.ReleaseArray((Array)ema2);
47 | }
48 |
49 | var result = Context?.GetArray(source.Count) ?? new double[source.Count];
50 | for (var i = 1; i < result.Length; i++)
51 | {
52 | var lastEma3 = ema3[i - 1];
53 | result[i] = lastEma3 != 0 ? (ema3[i] - lastEma3) / lastEma3 : 0;
54 | }
55 |
56 | if (!IsSimple)
57 | Context?.ReleaseArray((Array)ema3);
58 | return result;
59 | }
60 |
61 | protected override void InitExecuteContext()
62 | {
63 | m_lastEma3 = 0;
64 | if (IsSimple)
65 | return;
66 |
67 | m_ema1 = new EMA { Context = Context, Period = Period };
68 | m_ema2 = new EMA { Context = Context, Period = Period };
69 | m_ema3 = new EMA { Context = Context, Period = Period };
70 | }
71 |
72 | protected override void ClearExecuteContext()
73 | {
74 | m_lastEma3 = 0;
75 | m_ema1 = null;
76 | m_ema2 = null;
77 | m_ema3 = null;
78 | }
79 |
80 | protected override void InitForGap()
81 | {
82 | if (IsSimple)
83 | m_lastEma3 = m_executeContext.GetSourceForGap(m_executeContext.Index - 1);
84 | else
85 | {
86 | var firstIndex = Math.Max(m_executeContext.LastIndex + 1, m_executeContext.Index - 4 * Period);
87 | for (var i = firstIndex; i < m_executeContext.Index; i++)
88 | {
89 | var source = m_executeContext.GetSourceForGap(i);
90 | var ema1 = m_ema1.Execute(source, i);
91 | var ema2 = m_ema2.Execute(ema1, i);
92 | var ema3 = m_ema3.Execute(ema2, i);
93 | m_lastEma3 = ema3;
94 | }
95 | }
96 | }
97 |
98 | protected override double Execute()
99 | {
100 | double ema3;
101 | if (IsSimple)
102 | ema3 = m_executeContext.Source;
103 | else
104 | {
105 | var ema1 = m_ema1.Execute(m_executeContext.Source, m_executeContext.Index);
106 | var ema2 = m_ema2.Execute(ema1, m_executeContext.Index);
107 | ema3 = m_ema3.Execute(ema2, m_executeContext.Index);
108 | }
109 | var result = m_lastEma3 != 0 ? (ema3 - m_lastEma3) / m_lastEma3 : 0;
110 | m_lastEma3 = ema3;
111 | return result;
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/Other/EmptyDoubleHandler.cs:
--------------------------------------------------------------------------------
1 | namespace TSLab.Script.Handlers
2 | {
3 | [HandlerInvisible]
4 | [OutputType(TemplateTypes.DOUBLE)]
5 | public sealed class EmptyDoubleHandler : IHandler
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Other/TEST.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TSLab-Dev/Handlers/7bb483dce9ac034057762f73752236ff65e021f9/Other/TEST.cs
--------------------------------------------------------------------------------
/PortfolioHandlers/AgentHandlers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Utils;
5 |
6 | namespace TSLab.Script.Handlers.PortfolioHandlers
7 | {
8 | public interface IAgentTradingInfoService
9 | {
10 | double GetAgentLots(string symbol);
11 | }
12 |
13 | [HandlerCategory(HandlerCategories.Portfolio)]
14 | [HelperName("Agents lots", Language = Constants.En)]
15 | [InputsCount(1)]
16 | [Input(0, TemplateTypes.SECURITY, Name = "SECURITYSource")]
17 | [OutputsCount(1)]
18 | [OutputType(TemplateTypes.DOUBLE)]
19 | #if !DEBUG
20 | [HandlerInvisible]
21 | #endif
22 | public class AgentHandlers : IStreamHandler
23 | {
24 |
25 | public IList Execute(ISecurity source)
26 | {
27 | var value = 0.0;
28 | var symbol = source?.Symbol;
29 | if (!string.IsNullOrEmpty(symbol))
30 | {
31 | var service = Locator.Current.GetInstance();
32 | value = service.GetAgentLots(symbol);
33 | }
34 | return Enumerable.Repeat(value, source.Bars.Count).ToList();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/PortfolioHandlers/Portfolio.Enums.cs:
--------------------------------------------------------------------------------
1 | using TSLab.Utils;
2 |
3 | namespace TSLab.Script.Handlers
4 | {
5 | public enum PositionField
6 | {
7 | [LocalizeDescription("PositionField.RealRest")] // Текущая
8 | RealRest,
9 | [LocalizeDescription("PositionField.IncomeRest")] // Входящая
10 | IncomeRest,
11 | [LocalizeDescription("PositionField.PlanRest")] // Плановая
12 | PlanRest,
13 | [LocalizeDescription("PositionField.BalancePrice")] // Учетная цена
14 | BalancePrice,
15 | [LocalizeDescription("PositionField.AssessedPrice")] // Оценочная цена
16 | AssessedPrice,
17 | [LocalizeDescription("PositionField.Commission")] // Комиссия
18 | Commission,
19 | [LocalizeDescription("PositionField.Balance")] // Чистая стоимость
20 | Balance,
21 | [LocalizeDescription("PositionField.BalForwardVolume")] // Учетная стоимость
22 | BalForwardVolume,
23 | [LocalizeDescription("PositionField.ProfitVolume")] // НП/У
24 | ProfitVolume,
25 | [LocalizeDescription("PositionField.DailyPl")] // П/У (дн)
26 | DailyPl,
27 | [LocalizeDescription("PositionField.VarMargin")] // Вар.маржа
28 | VarMargin,
29 | }
30 |
31 | public enum AgentField
32 | {
33 | [LocalizeDescription("AgentField.Profit")] // П/У
34 | Profit,
35 |
36 | [LocalizeDescription("AgentField.DailyProfit")] // П/У (дн)
37 | DailyProfit,
38 |
39 | [LocalizeDescription("AgentField.ProfitVol")] // НП/У
40 | ProfitVol,
41 |
42 | [LocalizeDescription("AgentField.PositionInLots")] // Позиция (лоты)
43 | PositionInLots,
44 |
45 | [LocalizeDescription("AgentField.PositionInMoney")] // Позиция (деньги)
46 | PositionInMoney,
47 |
48 | [LocalizeDescription("AgentField.PositionLong")] // Длинная поз.(лоты)
49 | PositionLong,
50 |
51 | [LocalizeDescription("AgentField.PositionShort")] // Короткая поз.(лоты)
52 | PositionShort,
53 |
54 | [LocalizeDescription("AgentField.AssessedPrice")] // Оценочная цена
55 | AssessedPrice,
56 |
57 | [LocalizeDescription("AgentField.BalancePrice")] // Учетная цена
58 | BalancePrice,
59 |
60 | [LocalizeDescription("AgentField.LastPrice")] // Текущая цена
61 | LastPrice,
62 |
63 | [LocalizeDescription("AgentField.Commission")] // Комиссия
64 | Commission,
65 |
66 | [LocalizeDescription("AgentField.Slippage")] // Проскальзывание
67 | Slippage,
68 |
69 | [LocalizeDescription("AgentField.SlippagePercent")] // Проскальзывание %
70 | SlippagePercent,
71 | }
72 |
73 | public enum ProfitKind
74 | {
75 | [LocalizeDescription("ProfitKind.Unfixed")]
76 | Unfixed,
77 | [LocalizeDescription("ProfitKind.Fixed")]
78 | Fixed,
79 | [LocalizeDescription("ProfitKind.MaxFixed")]
80 | MaxFixed,
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Position/HoldSignalForNBars.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.Script.Handlers.Options;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.Position)]
10 | [HelperName("Hold signal for N bars", Language = Constants.En)]
11 | [HelperName("Удерживать сигнал N баров", Language = Constants.Ru)]
12 | [InputsCount(1)]
13 | [Input(0, TemplateTypes.BOOL)]
14 | [OutputsCount(1)]
15 | [OutputType(TemplateTypes.BOOL)]
16 | [Description("Удерживает сигнал 'Истина' в течение заданного количества баров после его появления.")]
17 | [HelperDescription("Holds a signal TRUE for some number of bars.", Constants.En)]
18 | public sealed class HoldSignalForNBars : IStreamHandler, IValuesHandlerWithNumber, IOneSourceHandler, IBooleanReturns, IBooleanInputs
19 | {
20 | private int m_lastTrueIndex = -1;
21 |
22 | ///
23 | /// \~english Hold signal for N bars
24 | /// \~russian Удерживать сигнал в течение N баров
25 | ///
26 | [HelperName("Bars count", Constants.En)]
27 | [HelperName("Количество баров", Constants.Ru)]
28 | [Description("Количество баров для продления сигнала")]
29 | [HelperDescription("Bars count to hold a signal", Constants.En)]
30 | [HandlerParameter(true, "0", Min = "0", Max = "10", Step = "1", EditorMin = "0")]
31 | public int NBars { get; set; }
32 |
33 | public IList Execute(IList source)
34 | {
35 | if (NBars <= 0 || source.Count <= 1 || source.All(item => item) || source.All(item => !item))
36 | return source;
37 |
38 | var result = new List(source);
39 | for (var i = 0; i < source.Count; i++)
40 | {
41 | if (source[i])
42 | {
43 | var jMax = Math.Min(i + NBars, source.Count - 1);
44 | for (var j = i + 1; j <= jMax; j++)
45 | result[j] = true;
46 | }
47 | }
48 | return result;
49 | }
50 |
51 | public bool Execute(bool value, int barIndex)
52 | {
53 | if (value)
54 | {
55 | m_lastTrueIndex = barIndex;
56 | return true;
57 | }
58 | return barIndex >= m_lastTrueIndex && barIndex <= m_lastTrueIndex + NBars;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Sources of the built-in TSLab handlers
2 |
3 | Исходные файлы встроенных TSLab обработчиков
--------------------------------------------------------------------------------
/ScriptCommonHandlers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | TSLab
6 | TSLab
7 | TSLab
8 | TSLab.Script.Handlers
9 | TSLab.Script.Handlers
10 | 3.0.0
11 | false
12 |
13 |
14 |
15 | true
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Service/ControlMessageHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Script.Optimization;
6 |
7 | // ReSharper disable once CheckNamespace
8 | namespace TSLab.Script.Handlers
9 | {
10 | [HandlerCategory(HandlerCategories.ServiceElements)]
11 | [HelperName("Control message", Language = Constants.En)]
12 | [HelperName("Контрольное сообщение", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.BOOL)]
15 | [OutputsCount(0)]
16 | [Description("Выводит контрольное сообщение")]
17 | [HelperDescription("Outputs control message", Constants.En)]
18 | public sealed class ControlMessageHandler : IOneSourceHandler, IBooleanReturns, IStreamHandler, IValuesHandlerWithNumber, IBooleanInputs, IContextUses, ICustomListValues
19 | {
20 | public IContext Context { get; set; }
21 |
22 | ///
23 | /// \~english True message
24 | /// \~russian Истинное сообщение
25 | ///
26 | [HelperName("True message", Constants.En)]
27 | [HelperName("Истинное сообщение", Constants.Ru)]
28 | [Description("Истинное сообщение")]
29 | [HelperDescription("True message", Constants.En)]
30 | [HandlerParameter(true, "")]
31 | public string TrueMessage { get; set; }
32 |
33 | ///
34 | /// \~english False message
35 | /// \~russian Ложное сообщение
36 | ///
37 | [HelperName("False message", Constants.En)]
38 | [HelperName("Ложное сообщение", Constants.Ru)]
39 | [Description("Ложное сообщение")]
40 | [HelperDescription("False message", Constants.En)]
41 | [HandlerParameter(true, "")]
42 | public string FalseMessage { get; set; }
43 |
44 | ///
45 | /// \~english Message
46 | /// \~russian Сообщение
47 | ///
48 | [HelperName("Message", Constants.En)]
49 | [HelperName("Сообщение", Constants.Ru)]
50 | [Description("Сообщение")]
51 | [HelperDescription("Message", Constants.En)]
52 | [HandlerParameter(true, "", IsCalculable = true)]
53 | public StringOptimProperty Message { get; set; }
54 |
55 | public void Execute(IList values)
56 | {
57 | if (values == null)
58 | throw new ArgumentNullException(nameof(values));
59 |
60 | if (values.Count > 0)
61 | Message.Value = values[values.Count - 1] ? TrueMessage : FalseMessage;
62 | else
63 | Message.Value = string.Empty;
64 | }
65 |
66 | public void Execute(bool value, int number)
67 | {
68 | if (number == Context.BarsCount - (Context.IsLastBarUsed ? 1 : 2))
69 | Message.Value = value ? TrueMessage : FalseMessage;
70 | }
71 |
72 | public IEnumerable GetValuesForParameter(string paramName)
73 | {
74 | yield return TrueMessage;
75 | yield return FalseMessage;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Service/EventKindHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.Script.Handlers.Options;
6 | using TSLab.Utils;
7 |
8 | // ReSharper disable once CheckNamespace
9 | namespace TSLab.Script.Handlers
10 | {
11 | public enum EventKind
12 | {
13 | [LocalizeDescription(nameof(EventKind) + "." + nameof(None))]
14 | None,
15 | [LocalizeDescription(nameof(EventKind) + "." + nameof(OrderRejected))]
16 | OrderRejected,
17 | [LocalizeDescription(nameof(EventKind) + "." + nameof(OrderFilled))]
18 | OrderFilled,
19 | [LocalizeDescription(nameof(EventKind) + "." + nameof(PositionOpening))]
20 | PositionOpening,
21 | [LocalizeDescription(nameof(EventKind) + "." + nameof(PositionClosing))]
22 | PositionClosing,
23 | [LocalizeDescription(nameof(EventKind) + "." + nameof(OrderQtyChanged))]
24 | OrderQtyChanged,
25 | [LocalizeDescription(nameof(EventKind) + "." + nameof(TradingIsStarted))]
26 | TradingIsStarted,
27 | [LocalizeDescription(nameof(EventKind) + "." + nameof(TradingIsStopped))]
28 | TradingIsStopped,
29 | [LocalizeDescription(nameof(EventKind) + "." + nameof(OrderCanceled))]
30 | OrderCanceled,
31 | [LocalizeDescription(nameof(EventKind) + "." + nameof(PretradeLimitation))]
32 | PretradeLimitation,
33 | }
34 |
35 | [HandlerCategory(HandlerCategories.ServiceElements)]
36 | [HelperName("Event", Language = Constants.En)]
37 | [HelperName("Событие", Language = Constants.Ru)]
38 | [InputsCount(1)]
39 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
40 | [OutputsCount(1)]
41 | [OutputType(TemplateTypes.BOOL)]
42 | [Description("Событие")]
43 | [HelperDescription("Event", Constants.En)]
44 | public sealed class EventKindHandler : IOneSourceHandler, IStreamHandler, ISecurityInputs, IContextUses
45 | {
46 | private static readonly IReadOnlyDictionary s_eventKindToNameMap = ((EventKind[])Enum.GetValues(typeof(EventKind))).ToDictionary(item => item, item => item.ToString());
47 |
48 | public IContext Context { get; set; }
49 |
50 | ///
51 | /// \~english Event kind
52 | /// \~russian Вид события
53 | ///
54 | [HelperName("Event kind", Constants.En)]
55 | [HelperName("Вид события", Constants.Ru)]
56 | [Description("Вид события")]
57 | [HelperDescription("Event kind", Constants.En)]
58 | [HandlerParameter(true, nameof(EventKind.None))]
59 | public EventKind EventKind { get; set; }
60 |
61 | public IList Execute(ISecurity source)
62 | {
63 | var strEventKind = s_eventKindToNameMap[EventKind];
64 | var sourceSecurityDescriptionId = source.SecurityDescription.Id;
65 | var result = Context.Runtime.LastRecalcReasons.Any(item => item.Name == strEventKind && item.DataSourceSecurity.Id == sourceSecurityDescriptionId);
66 | return new ConstList(source.Bars.Count, result);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Service/ExportValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.DataSource;
4 | using TSLab.Utils;
5 |
6 | // ReSharper disable once CheckNamespace
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.ServiceElements)]
10 | [OutputsCount(0)]
11 | public sealed class ExportValuesHandler : ITwoSourcesHandler, ISecurityInput0, IBooleanInput1, IDoubleInput1, IIntInput1, IStreamHandler, IValuesHandlerWithNumber, IContextUses
12 | {
13 | private bool[] m_boolValues;
14 | private double[] m_doubleValues;
15 | private int[] m_intValues;
16 |
17 | public IContext Context { get; set; }
18 |
19 | [HandlerParameter(true, "")]
20 | public string Id { get; set; }
21 |
22 | public void Execute(ISecurity security, IList values)
23 | {
24 | Export(security, values);
25 | }
26 |
27 | public void Execute(ISecurity security, IList values)
28 | {
29 | Export(security, values);
30 | }
31 |
32 | public void Execute(ISecurity security, IList values)
33 | {
34 | Export(security, values);
35 | }
36 |
37 | public void Execute(ISecurity security, bool value, int index)
38 | {
39 | Execute(security, value, index, ref m_boolValues);
40 | }
41 |
42 | public void Execute(ISecurity security, double value, int index)
43 | {
44 | Execute(security, value, index, ref m_doubleValues);
45 | }
46 |
47 | public void Execute(ISecurity security, int value, int index)
48 | {
49 | Execute(security, value, index, ref m_intValues);
50 | }
51 |
52 | private void Execute(ISecurity security, T value, int index, ref T[] values)
53 | {
54 | var barsCount = security.Bars.Count;
55 | (values ?? (values = new T[barsCount]))[index] = value;
56 |
57 | if (index == barsCount - 1)
58 | Export(security, values);
59 | }
60 |
61 | private void Export(ISecurity security, IList values)
62 | {
63 | if (Context.IsOptimization)
64 | return;
65 |
66 | var bars = security.Bars;
67 | var count = Math.Min(bars.Count, values.Count);
68 | var dateTimes = new DateTime[count];
69 |
70 | for (var i = 0; i < count; i++)
71 | dateTimes[i] = bars[i].Date;
72 |
73 | Context.StoreGlobalObject(Id, new NotClearableContainer(new Tuple, IList>(dateTimes, values)));
74 | }
75 |
76 | public IEnumerable GetValuesForParameter(string paramName)
77 | {
78 | if (paramName.EqualsIgnoreCase(nameof(Id)))
79 | return new[] { Id ?? "" };
80 | return new[] { "" };
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Service/HeartbeatHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using TSLab.Script.Handlers.Options;
4 |
5 | // ReSharper disable once CheckNamespace
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.ServiceElements)]
9 | [HelperName("Метроном 2", Language = Constants.Ru)]
10 | [HelperName("Heartbeat 2", Language = Constants.En)]
11 | [HandlerAlwaysKeep]
12 | [OutputsCount(0)]
13 | [Description("Метроном 2")]
14 | [HelperDescription("Heartbeat 2", Constants.En)]
15 | public sealed class HeartbeatHandler : IHandler, IZeroSourceHandler, IContextUses, INeedVariableId, INeedVariableName
16 | {
17 | public IContext Context { get; set; }
18 | public string VariableId { get; set; }
19 | public string VariableName { get; set; }
20 |
21 | [HelperName("Интервал", Constants.Ru)]
22 | [HelperName("Interval", Constants.En)]
23 | [Description("Интервал")]
24 | [HelperDescription("Interval", Language = Constants.En)]
25 | [HandlerParameter(true, "0:1:0", Min = "0:0:0", Max = "1.0:0:0", Step = "0:0:1", EditorMin = "0:0:0", EditorMax = "1.0:0:0")]
26 | public TimeSpan Interval { get; set; }
27 |
28 | public void Execute()
29 | {
30 | if (!Context.IsOptimization)
31 | HeartbeatManager.Instance.Register(this);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Service/HeartbeatManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using TSLab.Utils;
7 |
8 | // ReSharper disable once CheckNamespace
9 | namespace TSLab.Script.Handlers
10 | {
11 | internal sealed class HeartbeatManager
12 | {
13 | private sealed class Context
14 | {
15 | public IRuntime Runtime { get; set; }
16 | public string VariableId { get; set; }
17 | public string VariableName { get; set; }
18 | public TimeSpan Interval { get; set; }
19 | public DateTime CheckTime { get; set; }
20 | public bool IsBusy { get; set; }
21 | }
22 |
23 | public static readonly HeartbeatManager Instance = new HeartbeatManager();
24 | private readonly IDictionary m_contextsMap = new Dictionary();
25 |
26 | private HeartbeatManager()
27 | {
28 | var thread = ThreadProfiler.Create(ThreadStart);
29 | thread.IsBackground = true;
30 | thread.Name = nameof(HeartbeatManager) + "." + nameof(Thread);
31 | thread.Start();
32 | }
33 |
34 | public void Register(HeartbeatHandler handler)
35 | {
36 | var runtime = handler.Context.Runtime;
37 | var key = string.Join(".", runtime.TradeName, runtime.IsAgentMode, handler.VariableId);
38 |
39 | lock (m_contextsMap)
40 | if (m_contextsMap.TryGetValue(key, out var oldContext))
41 | {
42 | oldContext.Runtime = runtime;
43 | oldContext.VariableId = handler.VariableId;
44 | oldContext.VariableName = handler.VariableName;
45 | oldContext.Interval = handler.Interval;
46 | }
47 | else
48 | m_contextsMap[key] = new Context
49 | {
50 | Runtime = runtime,
51 | VariableId = handler.VariableId,
52 | VariableName = handler.VariableName,
53 | Interval = handler.Interval,
54 | };
55 | }
56 |
57 | private void ThreadStart()
58 | {
59 | while (true)
60 | {
61 | Thread.Sleep(1);
62 | var utcNow = DateTime.UtcNow;
63 |
64 | lock (m_contextsMap)
65 | foreach (var keyValuePair in m_contextsMap.ToArray())
66 | {
67 | var context = keyValuePair.Value;
68 | var runtime = context.Runtime;
69 |
70 | if (runtime.IsDisposedOrDisposing || (runtime.IsAgentMode && !runtime.IsRealTime))
71 | m_contextsMap.Remove(keyValuePair.Key);
72 | else if (!context.IsBusy && utcNow - context.CheckTime >= context.Interval)
73 | {
74 | if (!runtime.IsAgentMode && !runtime.IsRealTime)
75 | m_contextsMap.Remove(keyValuePair.Key);
76 | else
77 | {
78 | context.CheckTime = utcNow;
79 | context.IsBusy = true;
80 | Task.Factory.StartNew(() => Execute(context));
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
87 | private static void Execute(Context context)
88 | {
89 | try
90 | {
91 | var runtime = context.Runtime;
92 | if (runtime.IsDisposedOrDisposing)
93 | return;
94 |
95 | runtime.Recalc(RecalcReasons.Heartbeat2, null);
96 | }
97 | catch (Exception ex)
98 | {
99 | if (Logging.On) Logging.Exception(Logging.Handlers, "Heartbeat", ex);
100 | }
101 | finally
102 | {
103 | context.IsBusy = false;
104 | }
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Service/ImportBoolValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | // ReSharper disable once CheckNamespace
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed class ImportBoolValuesHandler : ImportValuesHandler, IBooleanReturns
8 | {
9 | protected override bool GetValue(IReadOnlyList values)
10 | {
11 | if (values.Count == 0)
12 | return default(bool);
13 |
14 | if (values.Count == 1)
15 | return values[0];
16 |
17 | var trueCount = values.Count(item => item);
18 | return trueCount >= values.Count - trueCount;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Service/ImportDoubleValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | // ReSharper disable once CheckNamespace
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed class ImportDoubleValuesHandler : ImportValuesHandler, IDoubleReturns
8 | {
9 | protected override double GetValue(IReadOnlyList values)
10 | {
11 | if (values.Count == 0)
12 | return default(double);
13 |
14 | if (values.Count == 1)
15 | return values[0];
16 |
17 | return values.Sum() / values.Count;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Service/ImportIntValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | // ReSharper disable once CheckNamespace
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed class ImportIntValuesHandler : ImportValuesHandler, IIntReturns
8 | {
9 | protected override int GetValue(IReadOnlyList values)
10 | {
11 | if (values.Count == 0)
12 | return default(int);
13 |
14 | if (values.Count == 1)
15 | return values[0];
16 |
17 | return values.Sum() / values.Count;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Service/ImportValuesHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.DataSource;
4 | using TSLab.Utils;
5 |
6 | // ReSharper disable once CheckNamespace
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.ServiceElements)]
10 | [InputsCount(1)]
11 | public abstract class ImportValuesHandler : IOneSourceHandler, ISecurityInputs, IStreamHandler, IContextUses
12 | {
13 | public IContext Context { get; set; }
14 |
15 | [HandlerParameter(true, "")]
16 | public string Id { get; set; }
17 |
18 | public IList Execute(ISecurity security)
19 | {
20 | var bars = security.Bars;
21 | var barsCount = bars.Count;
22 | var values = new T[barsCount];
23 |
24 | if (barsCount == 0 || !(Context.LoadGlobalObject(Id, null)?.Content is Tuple, IList> context))
25 | return values;
26 |
27 | var importedDateTimes = context.Item1;
28 | var importedValues = context.Item2;
29 | var importedCount = Math.Min(importedDateTimes.Count, importedValues.Count);
30 |
31 | if (importedCount == 0)
32 | return values;
33 |
34 | int index = 0, importedIndex = 0;
35 | var importedDateTime = importedDateTimes[0];
36 |
37 | while (index < barsCount && bars[index].Date < importedDateTime)
38 | values[index++] = default(T);
39 |
40 | var currentValues = new List();
41 | while (index < barsCount && importedIndex < importedCount)
42 | {
43 | importedDateTime = importedDateTimes[importedIndex];
44 | var barDate = bars[index].Date;
45 |
46 | if (importedDateTime <= barDate)
47 | currentValues.Add(importedValues[importedIndex++]);
48 | else
49 | {
50 | var value1 = GetValue(currentValues);
51 | while (index < barsCount && bars[index].Date < importedDateTime)
52 | values[index++] = value1;
53 |
54 | currentValues.Clear();
55 | }
56 | }
57 | var value2 = GetValue(currentValues);
58 | while (index < barsCount)
59 | values[index++] = value2;
60 |
61 | return values;
62 | }
63 |
64 | protected abstract T GetValue(IReadOnlyList values);
65 |
66 | public IEnumerable GetValuesForParameter(string paramName)
67 | {
68 | if (paramName.EqualsIgnoreCase(nameof(Id)))
69 | return new[] { Id ?? "" };
70 | return new[] { "" };
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Service/InstrumentByName.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Utils;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.ServiceElements)]
10 | [HelperName("Instrument by name", Language = Constants.En)]
11 | [HelperName("Инструмент по имени", Language = Constants.Ru)]
12 | [InputsCount(1)]
13 | [Input(0, TemplateTypes.MULTI_SECURITY, Name = Constants.SecuritySource)]
14 | [OutputsCount(1)]
15 | [OutputType(TemplateTypes.SECURITY)]
16 | [Description("Найти инструмент по имени в мульти-источнике. " +
17 | "Если инструмент не найден по имени, то возвращает первый по списку.")]
18 | [HelperDescription("Find the instrument by name in the multi-source. " +
19 | "If the instrument is not found by name, it returns the first one in the list.", Constants.En)]
20 | [NotCacheable]
21 | public class InstrumentByName : IStreamHandler, ISecurityReturns, ICustomListValues
22 | {
23 | [HelperName("Name", Constants.En)]
24 | [HelperName("Название", Constants.Ru)]
25 | [HandlerParameter(true, "")]
26 | public string Name { get; set; }
27 |
28 | private string[] m_names;
29 |
30 | public ISecurity Execute(ISecurity[] securities)
31 | {
32 | m_names = securities.Select(x => x.Symbol).ToArray();
33 | return securities.FirstOrDefault(x => x.Symbol.ContainsIgnoreCase(Name)) ?? securities.First();
34 | }
35 |
36 | public IEnumerable GetValuesForParameter(string paramName)
37 | {
38 | if (paramName.EqualsIgnoreCase(nameof(Name)))
39 | return m_names ?? new[] { "" };
40 | return new[] { "" };
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Service/InstrumentByNumber.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Utils;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.ServiceElements)]
9 | [HelperName("Instrument by number", Language = Constants.En)]
10 | [HelperName("Инструмент по нореру", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.MULTI_SECURITY, Name = Constants.SecuritySource)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.SECURITY)]
15 | [Description("Найти инструмент по номеру в мульти-источнике.")]
16 | [HelperDescription("Find the instrument by number in the multi-source.", Constants.En)]
17 | [NotCacheable]
18 | public class InstrumentByNumber : IStreamHandler, ISecurityReturns
19 | {
20 | [HelperName("Number", Constants.En)]
21 | [HelperName("Номер", Constants.Ru)]
22 | [HandlerParameter(true, "0")]
23 | public int Number { get; set; }
24 |
25 | public ISecurity Execute(ISecurity[] securities)
26 | {
27 | if (securities.Length > Number)
28 | return securities[Number];
29 | throw new Exception($"{RM.GetString("SecurityNotFound")}. Securities count: {securities.Length}, number: {Number}");
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Service/LoadFromGlobalCache2.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Script.Options;
5 | using TSLab.Utils;
6 |
7 | namespace TSLab.Script.Handlers
8 | {
9 | [HandlerCategory(HandlerCategories.ServiceElements)]
10 | [HelperName("Load from Global Cache", Language = Constants.En)]
11 | [HelperName("Загрузить из Глобального Кеша", Language = Constants.Ru)]
12 | [InputsCount(1)]
13 | [Input(0, TemplateTypes.SECURITY | TemplateTypes.OPTION_SERIES | TemplateTypes.OPTION, Name = Constants.AnyOption)]
14 | [OutputType(TemplateTypes.DOUBLE)]
15 | [Description("Загрузить значение индикатора из Глобального Кеша")]
16 | [HelperDescription("Load indicator from Global Cache", Constants.En)]
17 | public class LoadFromGlobalCache2 : IStreamHandler, IContextUses, ICustomListValues
18 | {
19 | [HelperName("Name", Constants.En)]
20 | [HelperName("Название", Constants.Ru)]
21 | [Description("Уникальное название в Глобальном Кеше")]
22 | [HelperDescription("Unique name in the Global Cache", Language = Constants.En)]
23 | [HandlerParameter(true, "MyCache")]
24 | public string Name { get; set; }
25 |
26 | [HelperName("Load from disk", Constants.En)]
27 | [HelperName("Загружать с диска", Constants.Ru)]
28 | [Description("Загружать значения из файла на диске для повторного использования между перезапусками программы")]
29 | [HelperDescription("Load from HDD to use indicator values across different program sessions", Language = Constants.En)]
30 | [HandlerParameter(true, "true")]
31 | public bool LoadFromStorage { get; set; }
32 |
33 | public IContext Context { get; set; }
34 |
35 | public IList Execute(ISecurity sec)
36 | {
37 | return Load(sec);
38 | }
39 |
40 | public IList Execute(IOption opt)
41 | {
42 | if ((opt == null) || (opt.UnderlyingAsset == null))
43 | return Constants.EmptyListDouble;
44 |
45 | var res = Execute(opt.UnderlyingAsset);
46 | return res;
47 | }
48 |
49 | public IList Execute(IOptionSeries optSer)
50 | {
51 | if ((optSer == null) || (optSer.UnderlyingAsset == null))
52 | return Constants.EmptyListDouble;
53 |
54 | var res = Execute(optSer.UnderlyingAsset);
55 | return res;
56 | }
57 |
58 | private IList Load(ISecurity sec)
59 | {
60 | var res = SaveToGlobalCache2.LoadDataByBars(Context, sec, Name, LoadFromStorage);
61 | return res;
62 | }
63 |
64 | public IEnumerable GetValuesForParameter(string paramName)
65 | {
66 | if (paramName.EqualsIgnoreCase(nameof(Name)))
67 | return new[] { Name ?? "" };
68 | return new[] { "" };
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Service/MessageHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.Script.Handlers.Options;
6 |
7 | // ReSharper disable once CheckNamespace
8 | namespace TSLab.Script.Handlers
9 | {
10 | [HandlerCategory(HandlerCategories.ServiceElements)]
11 | [HelperName("Message", Language = Constants.En)]
12 | [HelperName("Сообщение", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.BOOL)]
15 | [OutputsCount(0)]
16 | [Description("При появлении на входе блока значения 'Истина' выводит в лог программы пользовательское сообщение.")]
17 | [HelperDescription("When input becomes TRUE a handler sends user message to a TSLab log.", Constants.En)]
18 | public sealed class MessageHandler : IOneSourceHandler, IBooleanReturns, IStreamHandler, IValuesHandlerWithNumber, IBooleanInputs, IContextUses
19 | {
20 | private const string UserMessageTag = "$UserMessageTag";
21 | private int m_barIndex = -1;
22 | private int m_cycleIndex;
23 |
24 | public IContext Context { get; set; }
25 |
26 | ///
27 | /// \~english Message
28 | /// \~russian Сообщение
29 | ///
30 | [HelperName("Message", Constants.En)]
31 | [HelperName("Сообщение", Constants.Ru)]
32 | [Description("Сообщение")]
33 | [HelperDescription("Message", Constants.En)]
34 | [HandlerParameter(true, "", NotOptimized = true)]
35 | public string Message { get; set; }
36 |
37 | ///
38 | /// \~english Additional user tag
39 | /// \~russian Дополнительная пользовательская метка
40 | ///
41 | [HelperName("Tag", Constants.En)]
42 | [HelperName("Метка", Constants.Ru)]
43 | [Description("Дополнительная пользовательская метка")]
44 | [HelperDescription("Additional user tag", Constants.En)]
45 | [HandlerParameter(true, "Tag", NotOptimized = true)]
46 | public string Tag { get; set; }
47 |
48 | ///
49 | /// \~english Message importance (Info, Warning, Error)
50 | /// \~russian Важность сообщения (Info, Warning, Error)
51 | ///
52 | [HelperName("Importance", Constants.En)]
53 | [HelperName("Важность", Constants.Ru)]
54 | [Description("Важность сообщения (Info, Warning, Error)")]
55 | [HelperDescription("Message importance (Info, Warning, Error)", Constants.En)]
56 | [HandlerParameter(true, "Info", NotOptimized = true)]
57 | public MessageType Type { get; set; }
58 |
59 | public bool IsInCycle { get; set; }
60 |
61 | public void Execute(IList values)
62 | {
63 | if (values == null)
64 | throw new ArgumentNullException(nameof(values));
65 |
66 | if (values.LastOrDefault())
67 | Log(Message);
68 | }
69 |
70 | public void Execute(bool value, int barIndex)
71 | {
72 | if (IsInCycle)
73 | {
74 | if (m_barIndex != barIndex)
75 | {
76 | m_barIndex = barIndex;
77 | m_cycleIndex = 0;
78 | }
79 | else
80 | m_cycleIndex++;
81 | }
82 | if (value && barIndex == Context.BarsCount - (Context.IsLastBarUsed ? 1 : 2))
83 | Log(IsInCycle ? $"{Message} ({m_cycleIndex})" : Message);
84 | }
85 |
86 | public void Execute(IReadOnlyList> listOfLists)
87 | {
88 | if (listOfLists == null)
89 | throw new ArgumentNullException(nameof(listOfLists));
90 |
91 | if (listOfLists.Count == 0)
92 | return;
93 |
94 | var lastList = listOfLists.Last();
95 | var indexes = new List(lastList.Count);
96 |
97 | for (var i = 0; i < lastList.Count; i++)
98 | if (lastList[i])
99 | indexes.Add(i);
100 |
101 | if (indexes.Count > 0)
102 | Log($"{Message} ({string.Join(", ", indexes)})");
103 | }
104 |
105 | private void Log(string message)
106 | {
107 | var args = new Dictionary { { UserMessageTag, Tag ?? string.Empty } };
108 | Context.Log(message, Type, true, args);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/Service/TimestampHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.Utils;
4 |
5 | // ReSharper disable once CheckNamespace
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.ServiceElements)]
9 | public sealed class TimestampHandler : IBar2DoubleHandler, IContextUses
10 | {
11 | public IContext Context { get; set; }
12 |
13 | public IList Execute(ISecurity source)
14 | {
15 | if (source == null)
16 | throw new ArgumentNullException(nameof(source));
17 |
18 | var bars = source.Bars;
19 | var barsCount = bars.Count;
20 |
21 | if (barsCount == 0)
22 | return EmptyArrays.Double;
23 |
24 | var results = Context.GetArray(barsCount);
25 | for (var i = 0; i < barsCount; i++)
26 | results[i] = new DateTimeOffset(bars[i].Date).ToUnixTimeMilliseconds();
27 |
28 | return results;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/ShrinkedList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace TSLab.Script.Handlers
6 | {
7 | public sealed class ShrinkedList : IList
8 | {
9 | private readonly List m_list;
10 |
11 | public ShrinkedList(int capacity)
12 | {
13 | if (capacity < 1)
14 | throw new ArgumentOutOfRangeException(nameof(capacity));
15 |
16 | m_list = new List(capacity);
17 | }
18 |
19 | public IEnumerator GetEnumerator()
20 | {
21 | return m_list.GetEnumerator();
22 | }
23 |
24 | IEnumerator IEnumerable.GetEnumerator()
25 | {
26 | return m_list.GetEnumerator();
27 | }
28 |
29 | public void Add(T item)
30 | {
31 | if (m_list.Count == m_list.Capacity)
32 | m_list.RemoveAt(0);
33 |
34 | m_list.Add(item);
35 | }
36 |
37 | public void Clear()
38 | {
39 | m_list.Clear();
40 | }
41 |
42 | public bool Contains(T item)
43 | {
44 | return m_list.Contains(item);
45 | }
46 |
47 | public void CopyTo(T[] array, int arrayIndex)
48 | {
49 | m_list.CopyTo(array, arrayIndex);
50 | }
51 |
52 | public bool Remove(T item)
53 | {
54 | return m_list.Remove(item);
55 | }
56 |
57 | public int Count
58 | {
59 | get { return m_list.Count; }
60 | }
61 |
62 | public bool IsReadOnly
63 | {
64 | get { return ((IList)m_list).IsReadOnly; }
65 | }
66 |
67 | public int IndexOf(T item)
68 | {
69 | return m_list.IndexOf(item);
70 | }
71 |
72 | public void Insert(int index, T item)
73 | {
74 | m_list.Insert(index, item);
75 | }
76 |
77 | public void RemoveAt(int index)
78 | {
79 | m_list.RemoveAt(index);
80 | }
81 |
82 | public T this[int index]
83 | {
84 | get { return m_list[index]; }
85 | set { m_list[index] = value; }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/TSChannel/BoolReceiverHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Utils;
5 |
6 | namespace TSLab.Script.Handlers.TSChannel
7 | {
8 | [HandlerCategory(HandlerCategories.TSChannel)]
9 | [InputsCount(1, 2)]
10 | [Input(0, TemplateTypes.STRING, Name = Constants.SecuritySource)]
11 | [Input(1, TemplateTypes.STRING, Name = "Prefix")]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.BOOL)]
14 | [NotCacheable]
15 | public class BoolReceiverHandler : ConstGenBase, IStreamHandler, INeedVariableVisual, IContextUses
16 | {
17 | [HandlerParameter(NotOptimized = false)]
18 | public bool Value { get; set; }
19 |
20 |
21 | [HandlerParameter(true, "false")]
22 | public bool DefaultValue { get; set; }
23 |
24 | public IList Execute(IList receiver)
25 | {
26 | return Execute(receiver, null);
27 | }
28 |
29 | public IList Execute(IList receiver, IList prefix)
30 | {
31 | if (receiver.Count == 0)
32 | return Array.Empty();
33 |
34 | var v = Convert.ToDouble(DefaultValue);
35 | try
36 | {
37 | var service = Locator.Current.GetInstance();
38 | var pfx = prefix == null ? "" : prefix[0];
39 | var name = $"{pfx}{VariableVisual}";
40 | v = service.GetValue(receiver[0], name, v);
41 | }
42 | catch (Exception e)
43 | {
44 | Context.Log(e.Message, MessageType.Error);
45 | }
46 |
47 | var bv = Convert.ToBoolean(v);
48 | MakeList(receiver.Count, bv);
49 | Value = bv;
50 | return this;
51 | }
52 |
53 | public IContext Context { get; set; }
54 |
55 | public string VariableVisual { get; set; }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/TSChannel/ChannelHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Utils;
6 |
7 | namespace TSLab.Script.Handlers.TSChannel
8 | {
9 | [HandlerCategory(HandlerCategories.TSChannel)]
10 | [InputsCount(1,2)]
11 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
12 | [Input(1, TemplateTypes.BOOL, Name = "On/Off")]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.STRING)]
15 | public class ChannelHandler : ConstGenBase, IStreamHandler, ICustomListValues, IContextUses, INeedVariableVisual
16 | {
17 | [ApiKeyHandlerProperty(ApiKeyHandlerPropertyMode.Transmitter)]
18 | [HandlerParameter(NotOptimized = false, Editor = "TransmitterApiKeyEditor")]
19 | public string ChannelApiKey { get; set; }
20 |
21 | public IList Execute(ISecurity sec)
22 | {
23 | return ExecuteInternal(sec, true);
24 | }
25 |
26 | public IList Execute(ISecurity sec, IList enabled)
27 | {
28 | var isEnabled = enabled.LastOrDefault();
29 | return ExecuteInternal(sec, isEnabled);
30 | }
31 |
32 | private IList ExecuteInternal(ISecurity sec, bool isEnabled)
33 | {
34 | var channelApiKey = isEnabled ? ChannelApiKey : ""; // Making empty key to skip values
35 | MakeList(sec.Bars.Count, channelApiKey);
36 |
37 | if (Context.IsOptimization)
38 | return this;
39 |
40 | if (string.IsNullOrWhiteSpace(channelApiKey))
41 | {
42 | if (isEnabled)
43 | Context.Log($"Transmitter ApiKey'{VariableVisual}' doesn't set.", MessageType.Error);
44 | return this;
45 | }
46 |
47 | try
48 | {
49 | var service = Locator.Current.GetInstance();
50 | service.RegisterTransmitterForUpdates(sec, channelApiKey);
51 | }
52 | catch (Exception e)
53 | {
54 | Context.Log(e.Message, MessageType.Error);
55 | }
56 |
57 | return this;
58 | }
59 |
60 | public IContext Context { get; set; }
61 |
62 | public IEnumerable GetValuesForParameter(string paramName)
63 | {
64 | return new[] { ChannelApiKey };
65 | }
66 |
67 | public string VariableVisual { get; set; }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/TSChannel/IsReceiverOnline.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Utils;
5 |
6 | namespace TSLab.Script.Handlers.TSChannel
7 | {
8 | [HandlerCategory(HandlerCategories.TSChannel)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.STRING, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.BOOL)]
13 | [NotCacheable]
14 | public class IsReceiverOnline : ConstGenBase, IStreamHandler, IContextUses
15 | {
16 | public IList Execute(IList receiver)
17 | {
18 | if (receiver.Count == 0)
19 | return Array.Empty();
20 |
21 | var receiverApiKey = receiver[0];
22 | var dsName = (string)Context.LoadObject(receiverApiKey);
23 | var service = Locator.Current.GetInstance();
24 | var v = service.IsReceiverReady(receiverApiKey, dsName);
25 | MakeList(receiver.Count, v);
26 | return this;
27 | }
28 |
29 | public IContext Context { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/TSChannel/ParameterSenderHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.Script.Handlers.Options;
3 | using TSLab.Utils;
4 |
5 | namespace TSLab.Script.Handlers.TSChannel
6 | {
7 | [HandlerCategory(HandlerCategories.TSChannel)]
8 | [InputsCount(1, 2)]
9 | [Input(0, TemplateTypes.STRING, Name = Constants.SecuritySource)]
10 | [Input(1, TemplateTypes.STRING, Name = "Prefix")]
11 | [OutputsCount(0)]
12 | public class ParameterSenderHandler : IContextUses, INeedVariableVisual, IValuesHandlerWithNumber
13 | {
14 | ///
15 | /// \~english A value to return as output of a handler
16 | /// \~russian Значение на выходе блока
17 | ///
18 | [HandlerParameter(NotOptimized = false)]
19 | public double Value { get; set; }
20 |
21 | public void Execute(string apiKey, int bar)
22 | {
23 | Execute(apiKey, "", bar);
24 | }
25 |
26 | public void Execute(string apiKey, string prefix, int bar)
27 | {
28 | if (Context.IsOptimization)
29 | return;
30 | var barsCount = Context.BarsCount;
31 | if (!Context.IsLastBarUsed)
32 | barsCount--;
33 | if (bar != barsCount - 1)
34 | return;
35 | var service = Locator.Current.GetInstance();
36 | service.SetValue(apiKey, $"{prefix}{VariableVisual}", Value);
37 | }
38 |
39 | public IContext Context { get; set; }
40 |
41 | public string VariableVisual { get; set; }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/TSChannel/ReceiverHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Xml.Linq;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Utils;
6 |
7 | namespace TSLab.Script.Handlers.TSChannel
8 | {
9 | [HandlerCategory(HandlerCategories.TSChannel)]
10 | [InputsCount(1)]
11 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.STRING)]
14 | public class ReceiverHandler : ConstGenBase, IStreamHandler, IContextUses, ICustomListValues, INeedVariableVisual
15 | {
16 | [ApiKeyHandlerProperty(ApiKeyHandlerPropertyMode.Receiver)]
17 | [HandlerParameter(NotOptimized = false, IsTransparentSetValue = true, Editor = "ReceiverApiKeyEditor")]
18 | public string ReceiverApiKey { get; set; }
19 |
20 | [ApiKeyHandlerProperty(ApiKeyHandlerPropertyMode.Channel)]
21 | [HandlerParameter(NotOptimized = false, Editor = "ChannelApiKeyEditor")]
22 | public string ChannelApiKey { get; set; }
23 |
24 | public IList Execute(ISecurity sec)
25 | {
26 | var receiverApiKey = ReceiverApiKey;
27 | MakeList(sec.Bars.Count, receiverApiKey);
28 |
29 | if (Context.IsOptimization)
30 | return this;
31 | if (string.IsNullOrWhiteSpace(receiverApiKey))
32 | {
33 | Context.Log($"Receiver ApiKey'{VariableVisual}' doesn't set.", MessageType.Error);
34 | return this;
35 | }
36 |
37 | var service = Locator.Current.GetInstance();
38 | try
39 | {
40 | var dsName = sec.SecurityDescription.DSName;
41 | Context.StoreObject(receiverApiKey, dsName);
42 | service.RegisterReceiverForUpdates(receiverApiKey, ChannelApiKey, dsName,
43 | () => Context.Recalc("TSChannel", sec.SecurityDescription));
44 | }
45 | catch (Exception e)
46 | {
47 | Context.Log(e.Message, MessageType.Error);
48 | //MakeList(sec.Bars.Count, receiverApiKey);
49 | }
50 |
51 | return this;
52 | }
53 |
54 | public IContext Context { get; set; }
55 |
56 | public IEnumerable GetValuesForParameter(string paramName)
57 | {
58 | if (paramName.EqualsIgnoreCase(nameof(ReceiverApiKey)))
59 | return new[] { ReceiverApiKey };
60 | if (paramName.EqualsIgnoreCase(nameof(ChannelApiKey)))
61 | return new[] { ChannelApiKey };
62 | return EmptyArrays.String;
63 | }
64 |
65 | public string VariableVisual { get; set; }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/TSChannel/ValueReceiverHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Utils;
5 |
6 | namespace TSLab.Script.Handlers.TSChannel
7 | {
8 | [HandlerCategory(HandlerCategories.TSChannel)]
9 | [InputsCount(1, 2)]
10 | [Input(0, TemplateTypes.STRING, Name = Constants.SecuritySource)]
11 | [Input(1, TemplateTypes.STRING, Name = "Prefix")]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.DOUBLE)]
14 | [NotCacheable]
15 | public class ValueReceiverHandler : ConstGenBase, IStreamHandler, INeedVariableVisual, IContextUses
16 | {
17 | [HandlerParameter(NotOptimized = false)]
18 | public double Value { get; set; }
19 |
20 |
21 | [HandlerParameter(true, "0")]
22 | public double DefaultValue { get; set; }
23 |
24 | public IList Execute(IList receiver)
25 | {
26 | return Execute(receiver, null);
27 | }
28 |
29 | public IList Execute(IList receiver, IList prefix)
30 | {
31 | if (receiver.Count == 0)
32 | return Array.Empty();
33 |
34 | var service = Locator.Current.GetInstance();
35 | var v = DefaultValue;
36 |
37 | try
38 | {
39 | var pfx = prefix == null ? "" : prefix[0];
40 | var name = $"{pfx}{VariableVisual}";
41 | v = service.GetValue(receiver[0], name, DefaultValue);
42 | }
43 | catch (Exception e)
44 | {
45 | Context.Log(e.Message, MessageType.Error);
46 | }
47 |
48 | MakeList(receiver.Count, v);
49 | Value = v;
50 | return this;
51 | }
52 |
53 | public IContext Context { get; set; }
54 |
55 | public string VariableVisual { get; set; }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/TSChannel/ValueSenderHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.Script.Handlers.Options;
3 | using TSLab.Utils;
4 |
5 | namespace TSLab.Script.Handlers.TSChannel
6 | {
7 | [HandlerCategory(HandlerCategories.TSChannel)]
8 | [InputsCount(2, 3)]
9 | [Input(0, TemplateTypes.STRING, Name = Constants.SecuritySource)]
10 | [Input(1, TemplateTypes.DOUBLE | TemplateTypes.INT | TemplateTypes.BOOL, Name = "Value")]
11 | [Input(2, TemplateTypes.STRING, Name = "Prefix")]
12 | [OutputsCount(0)]
13 | public class ValueSenderHandler : ITwoSourcesHandler, IContextUses, INeedVariableVisual, IValuesHandlerWithNumber
14 | {
15 | public void Execute(string apiKey, bool v, int bar)
16 | {
17 | Execute(apiKey, v, "", bar);
18 | }
19 |
20 | public void Execute(string apiKey, bool v, string prefix, int bar)
21 | {
22 | Execute(apiKey, Convert.ToDouble(v), prefix, bar);
23 | }
24 |
25 | public void Execute(string apiKey, double v, int bar)
26 | {
27 | Execute(apiKey, v, "", bar);
28 | }
29 |
30 | public void Execute(string apiKey, double v, string prefix, int bar)
31 | {
32 | if (Context.IsOptimization)
33 | return;
34 |
35 | var barsCount = Context.BarsCount;
36 | if (!Context.IsLastBarUsed)
37 | barsCount--;
38 | if (bar != barsCount - 1)
39 | return;
40 | var service = Locator.Current.GetInstance();
41 | service.SetValue(apiKey, $"{prefix}{VariableVisual}", v);
42 | }
43 |
44 | public IContext Context { get; set; }
45 |
46 | public string VariableVisual { get; set; }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/TradeMath/BarNumber.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 |
6 | using TSLab.Script.Handlers.Options;
7 |
8 | namespace TSLab.Script.Handlers
9 | {
10 | // TODO: правильней назвать кубик Bar INDEX или Index of the bar
11 | [HandlerCategory(HandlerCategories.TradeMath)]
12 | [HelperName("Bar number", Language = Constants.En)]
13 | [HelperName("Номер бара", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.SECURITY | TemplateTypes.DOUBLE | TemplateTypes.INT | TemplateTypes.BOOL)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.DOUBLE)]
18 | [Description("Индекс элемента в списке баров или числовых значений.")]
19 | [HelperDescription("An index of an element in a list of bars or numeric values.", Constants.En)]
20 | public sealed class BarNumber : IOneSourceHandler, IDoubleReturns, IStreamHandler, ISecurityInputs, IDoubleInputs, IIntInputs, IBooleanInputs
21 | {
22 | ///
23 | /// Рудиментарная реализация интерфейса IList[double], которая для экономии памяти и повышения скорости
24 | /// обеспечивает только минимальный функционал. В качестве 'элементов' выступают индексы исходного списка баров.
25 | ///
26 | private sealed class IndexList : IList, IReadOnlyList
27 | {
28 | public IndexList(int count)
29 | {
30 | Count = count;
31 | }
32 |
33 | public IEnumerator GetEnumerator()
34 | {
35 | for (var i = 0; i < Count; i++)
36 | yield return i;
37 | }
38 |
39 | IEnumerator IEnumerable.GetEnumerator()
40 | {
41 | return GetEnumerator();
42 | }
43 |
44 | public void Add(double item)
45 | {
46 | throw new NotSupportedException();
47 | }
48 |
49 | public void Clear()
50 | {
51 | throw new NotSupportedException();
52 | }
53 |
54 | public bool Contains(double item)
55 | {
56 | return IndexOf(item) >= 0;
57 | }
58 |
59 | public void CopyTo(double[] array, int arrayIndex)
60 | {
61 | throw new NotSupportedException();
62 | }
63 |
64 | public bool Remove(double item)
65 | {
66 | throw new NotSupportedException();
67 | }
68 |
69 | public int Count { get; }
70 |
71 | public bool IsReadOnly => true;
72 |
73 | public int IndexOf(double item)
74 | {
75 | var indexOf = (int)item;
76 | if (item != indexOf)
77 | throw new ArgumentException(nameof(item));
78 |
79 | return indexOf >= 0 && indexOf < Count ? indexOf : -1;
80 | }
81 |
82 | public void Insert(int index, double item)
83 | {
84 | throw new NotSupportedException();
85 | }
86 |
87 | public void RemoveAt(int index)
88 | {
89 | throw new NotSupportedException();
90 | }
91 |
92 | public double this[int index]
93 | {
94 | get
95 | {
96 | if (index >= 0 && index < Count)
97 | return index;
98 |
99 | throw new ArgumentOutOfRangeException(nameof(index));
100 | }
101 | set => throw new NotSupportedException();
102 | }
103 | }
104 |
105 | public IList Execute(ISecurity security)
106 | {
107 | return new IndexList(security.Bars.Count);
108 | }
109 |
110 | public IList Execute(IList security)
111 | {
112 | return new IndexList(security.Count);
113 | }
114 |
115 | public IList Execute(IList security)
116 | {
117 | return new IndexList(security.Count);
118 | }
119 |
120 | public IList Execute(IList security)
121 | {
122 | return new IndexList(security.Count);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/TradeMath/BarsConstructorHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.DataSource;
6 | using TSLab.Script.Handlers.Options;
7 |
8 | // ReSharper disable once CheckNamespace
9 | namespace TSLab.Script.Handlers
10 | {
11 | [HandlerCategory(HandlerCategories.TradeMath)]
12 | [HelperName("Bars Constructor", Language = Constants.En)]
13 | [HelperName("Конструктор баров", Language = Constants.Ru)]
14 | [InputsCount(5)]
15 | [Input(0, TemplateTypes.DOUBLE, Name = "Open")]
16 | [Input(1, TemplateTypes.DOUBLE, Name = "Close")]
17 | [Input(2, TemplateTypes.DOUBLE, Name = "High")]
18 | [Input(3, TemplateTypes.DOUBLE, Name = "Low")]
19 | [Input(4, TemplateTypes.DOUBLE, Name = "Volume")]
20 | [OutputsCount(1)]
21 | [OutputType(TemplateTypes.SECURITY)]
22 | [Description("Кубик преобразует 5 числовых серий на входе в синтетический инструмент с барами. Порядок входов: открытие, закрытие, максимум, минимум, объем.")]
23 | [HelperDescription("Handler converts 5 input numeric series to a synthetic security with bars. Inputs are: open, close, high, low, volume.", Constants.En)]
24 | public sealed class BarsConstructorHandler : BarsConstructorBase, IFiveSourcesHandler, ISecurityReturns, IStreamHandler, IDoubleInputs, IContextUses, INeedVariableName
25 | {
26 | public IContext Context { get; set; }
27 | public string VariableName { get; set; }
28 |
29 | public ISecurity Execute(IList openList, IList closeList, IList highList, IList lowList, IList volumeList)
30 | {
31 | if (openList == null)
32 | throw new ArgumentNullException(nameof(openList));
33 |
34 | if (closeList == null)
35 | throw new ArgumentNullException(nameof(closeList));
36 |
37 | if (highList == null)
38 | throw new ArgumentNullException(nameof(highList));
39 |
40 | if (lowList == null)
41 | throw new ArgumentNullException(nameof(lowList));
42 |
43 | if (volumeList == null)
44 | throw new ArgumentNullException(nameof(volumeList));
45 |
46 | var security = Context.Runtime.Securities.First();
47 | var securityBars = security.Bars;
48 | var count = Math.Min(openList.Count, Math.Min(closeList.Count, Math.Min(highList.Count, Math.Min(lowList.Count, Math.Min(volumeList.Count, securityBars.Count)))));
49 | var bars = new IDataBar[count];
50 |
51 | for (var i = 0; i < count; i++)
52 | bars[i] = new DataBar(securityBars[i].Date, openList[i], highList[i], lowList[i], closeList[i], volumeList[i]);
53 |
54 | return new Security(bars, VariableName, security);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/TradeMath/BarsTickDataHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.DataSource;
6 | using TSLab.Script.Handlers.Options;
7 | using TSLab.Utils;
8 |
9 | // ReSharper disable once CheckNamespace
10 | namespace TSLab.Script.Handlers
11 | {
12 | [HandlerCategory(HandlerCategories.TradeMath)]
13 | [HelperName("Bars tick data", Language = Constants.En)]
14 | [HelperName("Бары котировочных данных", Language = Constants.Ru)]
15 | [InputsCount(1)]
16 | [Input(0, TemplateTypes.SECURITY, Name = "SECURITYSource")]
17 | [OutputsCount(1)]
18 | [OutputType(TemplateTypes.SECURITY)]
19 | [Description("Предназначен для работы с кешируемыми данными из котировок. Строит бары с интервалом источника. Для работы используйте секундный интервал источника. Например, 60 секунд.")]
20 | [HelperDescription("Designed to work with cached data from quotes. Builds bars with the source interval. To work, use the second interval of the source. For example, 60 seconds.", Constants.En)]
21 | public sealed class BarsTickDataHandler : BarsConstructorBase, ISecurityReturns, IStreamHandler, ISecurityInputs,
22 | IContextUses, INeedVariableName
23 | {
24 | [HelperName("Data quotes", Constants.En)]
25 | [HelperName("Данные котировок", Constants.Ru)]
26 | [HandlerParameter(true, nameof(BarsTickDataField.BuyCount))]
27 | public BarsTickDataField Field { get; set; }
28 | public IContext Context { get; set; }
29 | public string VariableName { get; set; }
30 |
31 | public ISecurity Execute(ISecurity security)
32 | {
33 | var newBars = new IDataBar[Context.BarsCount];
34 | for (int i = 0; i < newBars.Length; i++)
35 | {
36 | var bar = security.Bars[i];
37 | var trades = GetData(security, i, Field).ToList();
38 | if (trades.Count == 0)
39 | {
40 | newBars[i] = i > 0 ? newBars[i - 1] : new DataBar(bar.Date, 0, 0, 0, 0);
41 | }
42 | else
43 | {
44 | var open = trades.First();
45 | var high = trades.Max();
46 | var low = trades.Min();
47 | var close = trades.Last();
48 | newBars[i] = new DataBar(bar.Date, open, high, low, close);
49 | }
50 | }
51 | return new Security(newBars, VariableName, security);
52 | }
53 |
54 | private static IEnumerable GetData(ISecurity source, int barNum, BarsTickDataField field)
55 | {
56 | var trades = source.GetTrades(barNum);
57 | switch (field)
58 | {
59 | case BarsTickDataField.BuyCount:
60 | return trades.OfType().Select(x => x.BuyCount);
61 | case BarsTickDataField.SellCount:
62 | return trades.OfType().Select(x => x.SellCount);
63 | case BarsTickDataField.BidQty:
64 | return trades.OfType().Select(x => x.BidQty);
65 | case BarsTickDataField.AskQty:
66 | return trades.OfType().Select(x => x.AskQty);
67 | case BarsTickDataField.OpenInterest:
68 | return trades.Select(x => x.OpenInterest);
69 | }
70 | throw new NotImplementedException(field.ToString());
71 | }
72 | }
73 |
74 | public enum BarsTickDataField
75 | {
76 | [LocalizeDescription("BarsTickDataField.BuyCount")] // Количество заявок на Покупку
77 | BuyCount,
78 | [LocalizeDescription("BarsTickDataField.SellCount")] // Количество заявок на Продажу
79 | SellCount,
80 | [LocalizeDescription("BarsTickDataField.BidQty")] // Суммарный Спрос
81 | BidQty,
82 | [LocalizeDescription("BarsTickDataField.AskQty")] // Суммарное Предложение
83 | AskQty,
84 | [LocalizeDescription("BarsTickDataField.OpenInterest")] // Открытый интерес
85 | OpenInterest,
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/TradeMath/ConstGen.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TSLab-Dev/Handlers/7bb483dce9ac034057762f73752236ff65e021f9/TradeMath/ConstGen.cs
--------------------------------------------------------------------------------
/TradeMath/ControlledBoolBreaker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using TSLab.Script.Handlers.Options;
5 | using TSLab.Script.Optimization;
6 | using TSLab.Utils;
7 |
8 | namespace TSLab.Script.Handlers.TradeMath
9 | {
10 | [HandlerCategory(HandlerCategories.TradeMath)]
11 | [HelperName("Controlled Boolean Breaker", Language = Constants.En)]
12 | [HelperName("Управляемый логический разделитель", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.BOOL)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.BOOL)]
17 | public sealed class ControlledBoolBreaker : IOneSourceHandler, IBooleanReturns, IStreamHandler, IValuesHandler, IBooleanInputs, IContextUses
18 | {
19 | public IContext Context { get; set; }
20 |
21 | ///
22 | /// \~english A value to return as output of a handler
23 | /// \~russian Значение на выходе блока
24 | ///
25 | [HelperName("Value", Constants.En)]
26 | [HelperName("Значение", Constants.Ru)]
27 | [HandlerParameter]
28 | public BoolOptimProperty Value { get; set; }
29 |
30 | public IList Execute(IList source)
31 | {
32 | if (source == null)
33 | throw new ArgumentNullException(nameof(source));
34 |
35 | if (source.Count == 0)
36 | return EmptyArrays.Bool;
37 |
38 | if (source.Last())
39 | Value.Value = false;
40 |
41 | return new ConstList(source.Count, Value.Value);
42 | }
43 |
44 | public bool Execute(bool value, int index)
45 | {
46 | if (index != Context.BarsCount - (Context.IsLastBarUsed ? 1 : 2))
47 | return false;
48 |
49 | if (value)
50 | Value.Value = false;
51 |
52 | return Value.Value;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/TradeMath/ControlledBoolConst.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 |
6 | using TSLab.Script.Handlers.Options;
7 | using TSLab.Utils;
8 |
9 | namespace TSLab.Script.Handlers
10 | {
11 | [HandlerCategory(HandlerCategories.TradeMath)]
12 | [HelperName("Controlled Boolean Constant", Language = Constants.En)]
13 | [HelperName("Управляемая логическая константа", Language = Constants.Ru)]
14 | [InputsCount(1)]
15 | [Input(0, TemplateTypes.BOOL)]
16 | [OutputsCount(1)]
17 | [OutputType(TemplateTypes.BOOL)]
18 | [Description("Управляемая логическая константа (переключатель). При поступлении на вход значения 'Истина' данный блок выдает значение из поля 'Значение', при поступлении на вход значения 'Ложь' используется 'Значение по умолчанию'.")]
19 | [HelperDescription("Controlled boolean constant (switch). If input is TRUE the result is taken from a field 'Value', otherwise the result is taken from a field 'Default value'.", Constants.En)]
20 | public sealed class ControlledBoolConst : IOneSourceHandler, IBooleanReturns, IStreamHandler, IValuesHandler, IBooleanInputs, IContextUses
21 | {
22 | public IContext Context { get; set; }
23 |
24 | ///
25 | /// \~english A value to return as output of a handler when input is true
26 | /// \~russian Значение на выходе блока, если на вход подать 'Истина'
27 | ///
28 | [HelperName("Value", Constants.En)]
29 | [HelperName("Значение", Constants.Ru)]
30 | [Description("Значение на выходе блока, если на вход подать 'Истина'")]
31 | [HelperDescription("A value to return as output of a handler when input is true", Constants.En)]
32 | [HandlerParameter]
33 | public bool Value { get; set; }
34 |
35 | ///
36 | /// \~english A value to return as output of a handler when input is false
37 | /// \~russian Значение на выходе блока, если на вход подать 'Ложь'
38 | ///
39 | [HelperName("Default value", Constants.En)]
40 | [HelperName("Значение по умолчанию", Constants.Ru)]
41 | [Description("Значение на выходе блока, если на вход подать 'Ложь'")]
42 | [HelperDescription("A value to return as output of a handler when input is false", Constants.En)]
43 | [HandlerParameter(NotOptimized = true)]
44 | public bool DefaultValue { get; set; }
45 |
46 | public IList Execute(IList source)
47 | {
48 | if (source == null)
49 | throw new ArgumentNullException(nameof(source));
50 |
51 | if (source.Count == 0)
52 | return EmptyArrays.Bool;
53 |
54 | var firstValue = source[0];
55 | if (source.All(item => item == firstValue))
56 | return new ConstList(source.Count, firstValue ? Value : DefaultValue);
57 |
58 | var result = Context?.GetArray(source.Count) ?? new bool[source.Count];
59 | for (var i = 0; i < result.Length; i++)
60 | result[i] = source[i] ? Value : DefaultValue;
61 |
62 | return result;
63 | }
64 |
65 | public bool Execute(bool value, int index)
66 | {
67 | return value ? Value : DefaultValue;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/TradeMath/ExtremePos.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using TSLab.Script.Handlers.Options;
4 | using TSLab.Script.Helpers;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | ///
9 | /// Базовый класс для группы кубиков, которые вычисляют сколько прошло баров с предыдущего экстремума
10 | ///
11 | [HandlerCategory(HandlerCategories.TradeMath)]
12 | [InputsCount(1)]
13 | [Input(0, TemplateTypes.DOUBLE)]
14 | [OutputsCount(1)]
15 | [OutputType(TemplateTypes.DOUBLE)]
16 | public abstract class ExtremePos : IDouble2DoubleHandler, IContextUses
17 | {
18 | public IContext Context { get; set; }
19 |
20 | ///
21 | /// \~english Indicator period (processing window)
22 | /// \~russian Период индикатора (окно расчетов)
23 | ///
24 | [HelperName("Period", Constants.En)]
25 | [HelperName("Период", Constants.Ru)]
26 | [Description("Период индикатора (окно расчетов)")]
27 | [HelperDescription("Indicator period (processing window)", Constants.En)]
28 | [HandlerParameter(true, "20", Min = "10", Max = "100", Step = "5", EditorMin = "1")]
29 | public int Period { get; set; }
30 |
31 | public IList Execute(IList source)
32 | {
33 | var extremeValues = GetExtremeValues(source);
34 | var result = Context?.GetArray(source.Count) ?? new double[source.Count];
35 |
36 | for (var i = 1; i < result.Length; i++)
37 | {
38 | var k = 0;
39 | while (i - k >= 0 && extremeValues[i] != source[i - k])
40 | k++;
41 |
42 | result[i] = k;
43 | }
44 | return result;
45 | }
46 |
47 | protected abstract IList GetExtremeValues(IList source);
48 | }
49 |
50 | //[HandlerCategory(HandlerCategories.TradeMath)]
51 | // Категория и описание входов/выходов идет через базовый класс.
52 | [HelperName("Bars since last high", Language = Constants.En)]
53 | [HelperName("Баров с последнего максимума", Language = Constants.Ru)]
54 | [Description("Количество баров, прошедшее с момента последнего обновления максимума.")]
55 | [HelperDescription("The number of bars since the latest high.", Constants.En)]
56 | public sealed class HighestPos : ExtremePos
57 | {
58 | protected override IList GetExtremeValues(IList source)
59 | {
60 | return Series.Highest(source.AsReadOnly(), Period, Context);
61 | }
62 | }
63 |
64 | //[HandlerCategory(HandlerCategories.TradeMath)]
65 | // Категория и описание входов/выходов идет через базовый класс.
66 | [HelperName("Bars since last low", Language = Constants.En)]
67 | [HelperName("Баров с последнего минимума", Language = Constants.Ru)]
68 | [Description("Количество баров, прошедшее с момента последнего обновления минимума.")]
69 | [HelperDescription("The number of bars since the latest low.", Constants.En)]
70 | public sealed class LowestPos : ExtremePos
71 | {
72 | protected override IList GetExtremeValues(IList source)
73 | {
74 | return Series.Lowest(source.AsReadOnly(), Period, Context);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/TradeMath/FinInfoHandlers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 |
5 | using TSLab.DataSource;
6 | using TSLab.Script.Handlers.Options;
7 | using TSLab.Utils;
8 |
9 | namespace TSLab.Script.Handlers
10 | {
11 | ///
12 | /// Базовый класс для группы кубиков, которые используют FinInfo
13 | ///
14 | [HandlerCategory(HandlerCategories.TradeMath)]
15 | [InputsCount(1)]
16 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
17 | [OutputsCount(1)]
18 | [OutputType(TemplateTypes.DOUBLE)]
19 | public abstract class FinInfoHandler : IBar2DoubleHandler//, IContextUses
20 | {
21 | //public IContext Context { get; set; }
22 |
23 | public IList Execute(ISecurity source)
24 | {
25 | return new ConstList(source.Bars.Count, GetValue(source.FinInfo) ?? 0);
26 | }
27 |
28 | protected abstract double? GetValue(FinInfo finInfo);
29 | }
30 |
31 | // Гарантийные обязательства покупателя
32 | public sealed class BuyDeposit : FinInfoHandler
33 | {
34 | protected override double? GetValue(FinInfo finInfo)
35 | {
36 | return finInfo.BuyDeposit;
37 | }
38 | }
39 |
40 | // Гарантийные обязательства продавца
41 | public sealed class SellDeposit : FinInfoHandler
42 | {
43 | protected override double? GetValue(FinInfo finInfo)
44 | {
45 | return finInfo.SellDeposit;
46 | }
47 | }
48 |
49 | // Наибольшая цена спроса в течение торговой сессии
50 | public sealed class HighBid : FinInfoHandler
51 | {
52 | protected override double? GetValue(FinInfo finInfo)
53 | {
54 | return finInfo.HighBid;
55 | }
56 | }
57 |
58 | // Наименьшая цена предложения в течение торговой сессии
59 | public sealed class LowOffer : FinInfoHandler
60 | {
61 | protected override double? GetValue(FinInfo finInfo)
62 | {
63 | return finInfo.LowOffer;
64 | }
65 | }
66 |
67 | // Нижний лимит цены
68 | public sealed class PriceMin : FinInfoHandler
69 | {
70 | protected override double? GetValue(FinInfo finInfo)
71 | {
72 | return finInfo.PriceMin;
73 | }
74 | }
75 |
76 | // Верхний лимит цены
77 | public sealed class PriceMax : FinInfoHandler
78 | {
79 | protected override double? GetValue(FinInfo finInfo)
80 | {
81 | return finInfo.PriceMax;
82 | }
83 | }
84 |
85 | // Категория и описание входов/выходов идет через базовый класс.
86 | [HelperName("Price step", Language = Constants.En)]
87 | [HelperName("Шаг цены", Language = Constants.Ru)]
88 | [Description("Шаг цены инструмента. Эта же величина показывается в таблице 'Котировки'.")]
89 | [HelperDescription("Price step of a security. This value is shown also in 'Quotes' table.", Constants.En)]
90 | public sealed class Tick : FinInfoHandler
91 | {
92 | protected override double? GetValue(FinInfo finInfo)
93 | {
94 | if (finInfo == null || finInfo.Security == null)
95 | return 1;
96 |
97 | var lastPrice = finInfo.LastPrice ?? 0.0;
98 | var tick = finInfo.Security.GetTick(lastPrice);
99 | if (!DoubleUtil.IsPositive(tick))
100 | tick = Math.Pow(10, -finInfo.Security.Decimals);
101 |
102 | return tick;
103 | }
104 | }
105 |
106 | // Категория и описание входов/выходов идет через базовый класс.
107 | [HelperName("Lot step", Language = Constants.En)]
108 | [HelperName("Шаг лота", Language = Constants.Ru)]
109 | [Description("Шаг лота инструмента. Эта же величина показывается в таблице 'Котировки'.")]
110 | [HelperDescription("Lot step of a security. This value is shown also in 'Quotes' table.", Constants.En)]
111 | public sealed class LotTick : FinInfoHandler
112 | {
113 | protected override double? GetValue(FinInfo finInfo)
114 | {
115 | return finInfo?.Security?.LotTick;
116 | }
117 | }
118 |
119 | [HelperName("Lot size", Language = Constants.En)]
120 | [HelperName("Размер лота", Language = Constants.Ru)]
121 | [Description("Размер лота инструмента. Блок возвращает количество акций в одном лоте. Эта же величина показывается в таблице 'Котировки'.")]
122 | [HelperDescription("Lot size of a security. The block returns the number of shares in one lot. This value is shown also in 'Quotes' table.", Constants.En)]
123 | public sealed class LotSize : FinInfoHandler
124 | {
125 | protected override double? GetValue(FinInfo finInfo)
126 | {
127 | return finInfo?.Security?.LotSize;
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/TradeMath/Ln.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using TSLab.Script.Handlers.Options;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.TradeMath)]
9 | [HelperName("Ln", Language = Constants.En)]
10 | [HelperName("Ln", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.DOUBLE)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.DOUBLE)]
15 | [Description("Натуральный логарифм (Ln) для серии значений.")]
16 | [HelperDescription("A natural logarithm (Ln) for a values series.", Constants.En)]
17 | public sealed class Ln : IDouble2DoubleHandler, IValuesHandlerWithNumber
18 | {
19 | private double m_mult = 1, m_add = 0;
20 |
21 | ///
22 | /// \~english A result of logarithm may be multiplied by this coefficient ( Mult*LN(x) + Add )
23 | /// \~russian Результат логарифмирования можно сразу умножить на этот коэффициент ( Mult*LN(x) + Add )
24 | ///
25 | [HelperName("Multiply", Constants.En)]
26 | [HelperName("Множитель", Constants.Ru)]
27 | [Description("Результат логарифмирования можно сразу умножить на этот коэффициент ( Mult*LN(x) + Add )")]
28 | [HelperDescription("A result of logarithm may be multiplied by this coefficient ( Mult*LN(x) + Add )", Constants.En)]
29 | [HandlerParameter(true, Default = "1")]
30 | public double Mult
31 | {
32 | get { return m_mult; }
33 | set { m_mult = value; }
34 | }
35 |
36 | ///
37 | /// \~english A result of logarithm (after multiplication) may be shifted by this value ( Mult*LN(x) + Add )
38 | /// \~russian Результат логарифмирования (после домножения) можно увеличить на этот сдвиг ( Mult*LN(x) + Add )
39 | ///
40 | [HelperName("Add", Constants.En)]
41 | [HelperName("Прибавить", Constants.Ru)]
42 | [Description("Результат логарифмирования (после домножения) можно увеличить на этот сдвиг ( Mult*LN(x) + Add )")]
43 | [HelperDescription("A result of logarithm (after multiplication) may be shifted by this value ( Mult*LN(x) + Add )", Constants.En)]
44 | [HandlerParameter(true, Default = "0")]
45 | public double Add
46 | {
47 | get { return m_add; }
48 | set { m_add = value; }
49 | }
50 |
51 | ///
52 | /// Обработчик для интерфейса IStreamHandler
53 | ///
54 | public IList Execute(IList bars)
55 | {
56 | IList list = new List(bars.Count);
57 | for (int j = 0; j < bars.Count; j++)
58 | {
59 | double res = m_mult * Math.Log(bars[j]) + m_add;
60 | list.Add(res);
61 | }
62 | return list;
63 | }
64 |
65 | ///
66 | /// Обработчик для интерфейса IValuesHandlerWithNumber
67 | ///
68 | public double Execute(double barVal, int barNum)
69 | {
70 | double res = m_mult * Math.Log(barVal) + m_add;
71 | return res;
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/TradeMath/Multiply.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using TSLab.Script.Handlers.Options;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.TradeMath)]
9 | //[HandlerName("Multiply by Coef", Language = "en-US")]
10 | //[HandlerName("Умножить на число", Language = "ru-RU")]
11 | [HelperName("Multiply by", Language = Constants.En)]
12 | [HelperName("Умножить на", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.DOUBLE)]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Умножение каждого элемента входной серии на заданный коэффициент.")]
18 | [HelperDescription("Multiplies each item of input by a constant factor.", Constants.En)]
19 | public sealed class Multiply : IDouble2DoubleHandler, IValuesHandlerWithNumber, IContextUses
20 | {
21 | ///
22 | /// \~english Every item of input is multiplied by this coefficient ( Mult*x )
23 | /// \~russian Каждый элемент входной серии умножается на указанный коэффициент ( Mult*x )
24 | ///
25 | [HelperName("Multiply", Constants.En)]
26 | [HelperName("Множитель", Constants.Ru)]
27 | [Description("Каждый элемент входной серии умножается на указанный коэффициент ( Mult*x )")]
28 | [HelperDescription("Every item of input is multiplied by this coefficient ( Mult*x )", Constants.En)]
29 | [HandlerParameter(true, "2", Min = "0.5", Max = "5", Step = "0.5")]
30 | public double Coef
31 | {
32 | get;
33 | set;
34 | }
35 |
36 | ///
37 | /// Обработчик для интерфейса IStreamHandler
38 | ///
39 | public IList Execute(IList bars)
40 | {
41 | var count = bars.Count;
42 | var res = Context?.GetArray(count) ?? new double[count];
43 | for (var index = 0; index < bars.Count; index++)
44 | {
45 | res[index] = bars[index] * Coef;
46 | }
47 |
48 | return res;
49 | }
50 |
51 | ///
52 | /// Обработчик для интерфейса IValuesHandlerWithNumber
53 | ///
54 | public double Execute(double barVal, int barNum)
55 | {
56 | var res = barVal * Coef;
57 | return res;
58 | }
59 |
60 | public IContext Context { get; set; }
61 | }
62 | }
--------------------------------------------------------------------------------
/TradeMath/OrderBookPrice.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 |
7 | [HandlerCategory(HandlerCategories.TradeMath)]
8 | [HelperName("OrderBookPrice", Language = Constants.En)]
9 | [HelperName("OrderBookPrice", Language = Constants.Ru)]
10 | [InputsCount(1)]
11 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
12 | [OutputsCount(1)]
13 | [OutputType(TemplateTypes.DOUBLE)]
14 | public sealed class OrderBookPrice : IBar2ValueDoubleHandler
15 | {
16 | [HandlerParameter]
17 | public bool Buy { get; set; }
18 | [HandlerParameter(Min = "0", Default = "0")]
19 | public int Index { get; set; }
20 |
21 | public double Execute(ISecurity sec, int barNum)
22 | {
23 | var qds = Buy ? sec.GetBuyQueue(0) : sec.GetSellQueue(0);
24 | if (qds?.Count > 0 && Index >= 0 && qds.Count > Index)
25 | {
26 | var qd = qds[Index];
27 | return qd?.Price ?? 0.0;
28 | }
29 |
30 | return 0d;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TradeMath/OrderBookQty.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.TradeMath)]
7 | [HelperName("OrderBookQuantity", Language = Constants.En)]
8 | [HelperName("OrderBookQuantity", Language = Constants.Ru)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.DOUBLE)]
13 | public sealed class OrderBookQty : IBar2ValueDoubleHandler
14 | {
15 | [HandlerParameter]
16 | public bool Buy { get; set; }
17 | [HandlerParameter(Min = "0", Default= "0")]
18 | public int Index { get; set; }
19 |
20 | public double Execute(ISecurity sec, int barNum)
21 | {
22 | var qds = Buy ? sec.GetBuyQueue(0) : sec.GetSellQueue(0);
23 | if (qds?.Count > 0 && Index >= 0 && qds.Count > Index)
24 | {
25 | var qd = qds[Index];
26 | return qd?.Quantity ?? 0.0;
27 | }
28 |
29 | return 0d;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/TradeMath/OrderBookTotal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.TradeMath)]
7 | [HelperName("OrderBookTotal", Language = Constants.En)]
8 | [HelperName("OrderBookTotal", Language = Constants.Ru)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.DOUBLE)]
13 | public class OrderBookTotal : IBar2ValueDoubleHandler
14 | {
15 | [HandlerParameter]
16 | public bool Buy { get; set; }
17 | [HandlerParameter(Min = "0", Default = "0")]
18 | public int NumberRows { get; set; }
19 |
20 | public double Execute(ISecurity sec, int barNum)
21 | {
22 | if (NumberRows > 0)
23 | {
24 | var qds = Buy ? sec.GetBuyQueue(0) : sec.GetSellQueue(0);
25 | if (qds?.Count > 0)
26 | {
27 | var cnt = qds.Count > NumberRows ? NumberRows : qds.Count;
28 | double total = 0d;
29 | for (int i = 0; i < cnt; i++)
30 | {
31 | var qd = qds[i];
32 | total += qd.Quantity;
33 | }
34 | return total;
35 | }
36 | }
37 |
38 | return 0d;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TradeMath/RandomHandler.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TSLab-Dev/Handlers/7bb483dce9ac034057762f73752236ff65e021f9/TradeMath/RandomHandler.cs
--------------------------------------------------------------------------------
/TradeMath/ResettableControlledBoolConst.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 |
6 | using TSLab.Script.Handlers.Options;
7 | using TSLab.Script.Optimization;
8 | using TSLab.Utils;
9 |
10 | namespace TSLab.Script.Handlers
11 | {
12 | [HandlerCategory(HandlerCategories.TradeMath)]
13 | [HelperName("Resettable Controlled Boolean Constant", Language = Constants.En)]
14 | [HelperName("Сбрасываемая управляемая логическая константа", Language = Constants.Ru)]
15 | [InputsCount(2)]
16 | [Input(0, TemplateTypes.BOOL)]
17 | [Input(1, TemplateTypes.BOOL)]
18 | [OutputsCount(1)]
19 | [OutputType(TemplateTypes.BOOL)]
20 | [Description("Сбрасываемая управляемая логическая константа (переключатель). " +
21 | "При поступлении на вход значения 'Истина' данный блок выдает значение из поля 'Значение', при поступлении на вход значения 'Ложь' используется 'Значение по умолчанию'. " +
22 | "Второй вход определяет чему равно 'Значение'. Если в нем больше истин, то 'Значение' становится равно 'Значению по умолчанию'.")]
23 | [HelperDescription("Resettable controlled boolean constant (switch). " +
24 | "If input is TRUE the result is taken from a field 'Value', otherwise the result is taken from a field 'Default value'. " +
25 | "Second input determines 'Value'. If it contains more TRUE, then 'Value' is set to 'Default value'.", Constants.En)]
26 | public sealed class ResettableControlledBoolConst : ITwoSourcesHandler, IBooleanReturns, IStreamHandler, IValuesHandlerWithNumber, IBooleanInputs, IContextUses
27 | {
28 | public IContext Context { get; set; }
29 |
30 | ///
31 | /// \~english A value to return as output of a handler when input is true
32 | /// \~russian Значение на выходе блока, если на вход подать 'Истина'
33 | ///
34 | [HelperName("Value", Constants.En)]
35 | [HelperName("Значение", Constants.Ru)]
36 | [Description("Значение на выходе блока, если на вход подать 'Истина'")]
37 | [HelperDescription("A value to return as output of a handler when input is true", Constants.En)]
38 | [HandlerParameter]
39 | public BoolOptimProperty Value { get; set; }
40 |
41 | ///
42 | /// \~english A value to return as output of a handler when input is false
43 | /// \~russian Значение на выходе блока, если на вход подать 'Ложь'
44 | ///
45 | [HelperName("Default value", Constants.En)]
46 | [HelperName("Значение по умолчанию", Constants.Ru)]
47 | [Description("Значение на выходе блока, если на вход подать 'Ложь'")]
48 | [HelperDescription("A value to return as output of a handler when input is false", Constants.En)]
49 | [HandlerParameter(NotOptimized = true)]
50 | public bool DefaultValue { get; set; }
51 |
52 | public IList Execute(IList source, IList resetValues)
53 | {
54 | if (source == null)
55 | throw new ArgumentNullException(nameof(source));
56 |
57 | if (resetValues == null)
58 | throw new ArgumentNullException(nameof(resetValues));
59 |
60 | var count = Math.Min(source.Count, resetValues.Count);
61 | if (count == 0)
62 | return EmptyArrays.Bool;
63 |
64 | if (resetValues[count - 1])
65 | Value.Value = DefaultValue;
66 |
67 | var firstValue = source[0];
68 | if (source.Take(count).All(item => item == firstValue))
69 | return new ConstList(count, firstValue ? Value : DefaultValue);
70 |
71 | var result = Context?.GetArray(count) ?? new bool[count];
72 | for (var i = 0; i < result.Length; i++)
73 | result[i] = source[i] ? Value : DefaultValue;
74 |
75 | return result;
76 | }
77 |
78 | public bool Execute(bool source, bool resetValue, int number)
79 | {
80 | if (resetValue && number == Context.BarsCount - (Context.IsLastBarUsed ? 1 : 2))
81 | Value.Value = DefaultValue;
82 |
83 | var result = source ? Value : DefaultValue;
84 | return result;
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/TradeMath/ResultForOptimization.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.TradeMath)]
7 | [InputsCount(1)]
8 | [Input(0, TemplateTypes.DOUBLE)]
9 | [OutputsCount(0)]
10 | public class ResultForOptimization : IOneSourceHandler, IValuesHandler, IStreamHandler, IDoubleInputs, IDoubleReturns,
11 | IContextUses, INeedVariableVisual
12 | {
13 | public IContext Context { set; get; }
14 | public string VariableVisual { get; set; }
15 |
16 | public IList Execute(IList values)
17 | {
18 | var count = values.Count;
19 |
20 | if (count < 1)
21 | return new double[0];
22 |
23 | Context.ScriptResults[VariableVisual] = values.Last();
24 | return values;
25 | }
26 |
27 | public double Execute(double value, int barNum)
28 | {
29 | Context.ScriptResults[VariableVisual] = value;
30 | return value;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TradeMath/TextHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using TSLab.Script.Handlers.Options;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.TradeMath)]
9 | [HelperName("Text", Language = Constants.En)]
10 | [HelperName("Текст", Language = Constants.Ru)]
11 | [InputsCount(0)]
12 | [Description("Блок без входов. Содержит редактируемый строковый параметр, который будет возвращаться из блока в качестве результата его работы.")]
13 | [HelperDescription("This block has no entries. It has an editable text parameter which returns as a result of its work.", Constants.En)]
14 | public sealed class TextHandler : ConstGenBase, IStreamHandler, IStringReturns, ICustomListValues, IContextUses
15 | {
16 | public IContext Context { get; set; }
17 |
18 | ///
19 | /// \~english Text (string)
20 | /// \~russian Текст (строка)
21 | ///
22 | [HelperName("Text", Constants.En)]
23 | [HelperName("Текст", Constants.Ru)]
24 | [Description("Текст (строка)")]
25 | [HelperDescription("Text (string)", Constants.En)]
26 | [HandlerParameter(Default = "*")]
27 | public string Text { get; set; }
28 |
29 | public IList Execute()
30 | {
31 | MakeList(Context.BarsCount, Text);
32 | return this;
33 | }
34 |
35 | public IEnumerable GetValuesForParameter(string paramName)
36 | {
37 | return new[] { Text };
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/TradeMath/ValueSupportedIndicator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [Obsolete]
7 | [InputsCount(1)]
8 | [Input(0, TemplateTypes.DOUBLE, Name = "ItemConnector.Src")]
9 | public abstract class ValueSupportedIndicator : IValuesHandlerWithNumber, IDoubleReturns, IContextUses
10 | {
11 | private double[] m_result, m_source;
12 |
13 | public double Execute(double source, int i)
14 | {
15 | if (i < 0 || i >= Context.BarsCount)
16 | throw new ArgumentOutOfRangeException(nameof(i));
17 |
18 | if (m_result == null)
19 | {
20 | m_result = Context.GetArray(Context.BarsCount);
21 | m_source = Context.GetArray(Context.BarsCount);
22 | }
23 | m_source[i] = source;
24 | return Execute(m_source, m_result, i);
25 | }
26 |
27 | protected abstract double Execute(IList source, IList result, int num);
28 |
29 | public IContext Context { get; set; }
30 | }
31 |
32 | [Obsolete]
33 | public abstract class ValueSupportedIndicatorWithPeriod : ValueSupportedIndicator
34 | {
35 | private int m_period = 1;
36 |
37 | [HandlerParameter(true, "20", Min = "10", Max = "100", Step = "5", EditorMin = "1")]
38 | public int Period
39 | {
40 | get { return m_period; }
41 | set { m_period = Math.Max(value, 1); }
42 | }
43 | }
44 |
45 | [InputsCount(2)]
46 | [Input(0, TemplateTypes.DOUBLE)]
47 | [Input(1, TemplateTypes.DOUBLE)]
48 | public abstract class ValueSupportedComparer : IValuesHandlerWithNumber, IBooleanReturns, IContextUses
49 | {
50 | private bool[] m_data;
51 | private double[] m_source1, m_source2;
52 |
53 | public bool Execute(double source1, double source2, int i)
54 | {
55 | if (m_data == null)
56 | {
57 | m_data = Context.GetArray(Context.BarsCount);
58 | m_source1 = Context.GetArray(Context.BarsCount);
59 | m_source2 = Context.GetArray(Context.BarsCount);
60 | }
61 | m_source1[i] = source1;
62 | m_source2[i] = source2;
63 | return Execute(m_source1, m_source2, m_data, i);
64 | }
65 |
66 | protected abstract bool Execute(IList source1, IList source2, IList data, int num);
67 |
68 | public IContext Context { get; set; }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/TradeMath/WeightedAveragePrice.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Linq;
4 | using TSLab.DataSource;
5 | using TSLab.Script.Handlers.Options;
6 | using TSLab.Utils;
7 |
8 | namespace TSLab.Script.Handlers
9 | {
10 | [HandlerCategory(HandlerCategories.TradeMath)]
11 | [HelperName("Weighted average bar price", Language = Constants.En)]
12 | [HelperName("Средневзвешенная цена бара", Language = Constants.Ru)]
13 | [InputsCount(1)]
14 | [Input(0, TemplateTypes.SECURITY, Name = "SECURITYSource")]
15 | [OutputsCount(1)]
16 | [OutputType(TemplateTypes.DOUBLE)]
17 | [Description("Блок считает средневзвешенную цену бара, основываясь на сделках по инструменту. " +
18 | "Для правильной работы используйте секундный график. 1 мин = 60 сек.")]
19 | [HelperDescription("The block contains the weighted average price of a bar, about on trades on the instrument. " +
20 | "For correct work, use the second chart. 1 min = 60 sec.", Constants.En)]
21 | public class WeightedAveragePrice : IStreamHandler, IContextUses
22 | {
23 | [HelperName("Direction trades", Constants.En)]
24 | [HelperName("Направление сделок", Constants.Ru)]
25 | [HandlerParameter(true, nameof(TradeDirection2.All))]
26 | public TradeDirection2 Direction { get; set; }
27 |
28 | public IContext Context { get; set; }
29 |
30 | public IList Execute(ISecurity source)
31 | {
32 | var res = Context.GetArray(Context.BarsCount);
33 | for (int i = 0; i < res.Length; i++)
34 | {
35 | var trades = GetTrades(source, i, Direction).ToList();
36 | var value = trades.Sum(x => x.Quantity * x.Price) / trades.Sum(x => x.Quantity);
37 | res[i] = DoubleUtil.IsNumber(value) ? value : i > 0 ? res[i - 1] : 0;
38 | }
39 | return res;
40 | }
41 |
42 | private static IEnumerable GetTrades(ISecurity source, int barNum, TradeDirection2 direction)
43 | {
44 | var tradesAll = source.GetTrades(barNum);
45 | switch (direction)
46 | {
47 | case TradeDirection2.Buys:
48 | return tradesAll.Where(x => x.Direction == TradeDirection.Buy);
49 | case TradeDirection2.Sells:
50 | return tradesAll.Where(x => x.Direction == TradeDirection.Sell);
51 | default:
52 | return tradesAll;
53 | }
54 | }
55 | }
56 |
57 | public enum TradeDirection2
58 | {
59 | [LocalizeDescription("TradeDirection2.All")] // Все
60 | All,
61 | [LocalizeDescription("TradeDirection2.Buys")] // Покупки
62 | Buys,
63 | [LocalizeDescription("TradeDirection2.Sells")] // Продажи
64 | Sells,
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ValueUpdaterExecutionOrder.cs:
--------------------------------------------------------------------------------
1 | using TSLab.Utils;
2 |
3 | namespace TSLab.Script.Handlers
4 | {
5 | public enum ValueUpdaterExecutionOrder
6 | {
7 | [LocalizeDescription("ValueUpdaterExecutionOrder.Common")]
8 | Common,
9 | [LocalizeDescription("ValueUpdaterExecutionOrder.AtTheEnd")]
10 | AtTheEnd,
11 | [LocalizeDescription("ValueUpdaterExecutionOrder.AfterExit")]
12 | AfterExit,
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/VolumeAnalysis/BuysHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.VolumeAnalysis)]
7 | [HelperName("Buys", Language = Constants.En)]
8 | [HelperName("Покупки", Language = Constants.Ru)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.DOUBLE)]
13 | [Description("Показывает характеристики (количество или суммарный объем) сделок на покупку")]
14 | [HelperDescription("A handler calculates statistics (amount or total volume) of a long trades", Constants.En)]
15 | public sealed class BuysHandler : BuysSellsHandler
16 | {
17 | protected override double GetValue(ICachedTradeHistogram histogram)
18 | {
19 | return histogram.AskQuantity;
20 | }
21 |
22 | protected override int GetCount(ICachedTradeHistogram histogram)
23 | {
24 | return histogram.AskTradesCount;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/VolumeAnalysis/BuysMinusSellsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.VolumeAnalysis)]
7 | [HelperName("Buys Minus Sells", Language = Constants.En)]
8 | [HelperName("Покупки минус продажи", Language = Constants.Ru)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.DOUBLE)]
13 | [Description("Показывает разницу характеристик (количество или суммарный объем) сделок на покупку и на продажу")]
14 | [HelperDescription("A handler calculates statistics difference (amount or total volume) of a long and short trades", Constants.En)]
15 | public sealed class BuysMinusSellsHandler : BuysSellsHandler
16 | {
17 | protected override double GetValue(ICachedTradeHistogram histogram)
18 | {
19 | return histogram.DeltaAskBidQuantity;
20 | }
21 |
22 | protected override int GetCount(ICachedTradeHistogram histogram)
23 | {
24 | return histogram.AskTradesCount - histogram.BidTradesCount;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/VolumeAnalysis/BuysSellsHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using TSLab.Script.Handlers.Options;
6 | using TSLab.Utils;
7 |
8 | namespace TSLab.Script.Handlers
9 | {
10 | //[HandlerCategory(HandlerCategories.VolumeAnalysis)]
11 | // Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов. Это снижает гибкость управления в перспективе.
12 | public abstract class BuysSellsHandler : IBuysSellsHandler
13 | {
14 | public IContext Context { get; set; }
15 |
16 | ///
17 | /// \~english Market volume quantity units (shares, lots, trades count)
18 | /// \~russian Режим отображения рыночной статистики (объем, лоты, количество сделок)
19 | ///
20 | [HelperName("Quantity units", Constants.En)]
21 | [HelperName("Единицы объема", Constants.Ru)]
22 | [Description("Режим отображения рыночной статистики (объем, лоты, количество сделок)")]
23 | [HelperDescription("Market volume quantity units (shares, lots, trades count)", Constants.En)]
24 | [HandlerParameter(true, nameof(QuantityMode.Quantity))]
25 | public QuantityMode QuantityMode { get; set; }
26 |
27 | public IList Execute(ISecurity security)
28 | {
29 | if (security == null)
30 | throw new ArgumentNullException(nameof(security));
31 |
32 | var quantityMode = QuantityMode;
33 | if (quantityMode != QuantityMode.Quantity && quantityMode != QuantityMode.QuantityInLots && quantityMode != QuantityMode.TradesCount)
34 | throw new InvalidEnumArgumentException(nameof(QuantityMode), (int)quantityMode, quantityMode.GetType());
35 |
36 | var compressedBars = security.Bars;
37 | var compressedBarsCount = compressedBars.Count;
38 |
39 | if (compressedBarsCount == 0)
40 | return EmptyArrays.Double;
41 |
42 | var decompressedSecurity = Context.Runtime.Securities.First(
43 | item => item.SecurityDescription.Id == security.SecurityDescription.Id
44 | && item.SecurityDescription.DSName == security.SecurityDescription.DSName);
45 | var decompressedBars = decompressedSecurity.Bars;
46 | var decompressedBarsCount = decompressedBars.Count;
47 | var decompressedIndex = 0;
48 | var getValueFunc = GetValueFunc(decompressedSecurity);
49 | double[] results;
50 |
51 | if (ReferenceEquals(decompressedSecurity, security))
52 | {
53 | results = Context.GetArray(decompressedBarsCount);
54 | while (decompressedIndex < decompressedBarsCount)
55 | results[decompressedIndex] = getValueFunc(decompressedIndex++);
56 | }
57 | else
58 | {
59 | results = Context.GetArray(compressedBarsCount);
60 | var lastCompressedIndex = compressedBarsCount - 1;
61 | double compressedResult;
62 |
63 | for (var compressedIndex = 0; compressedIndex < lastCompressedIndex; compressedIndex++)
64 | {
65 | var nextCompressedDate = compressedBars[compressedIndex + 1].Date;
66 | compressedResult = 0;
67 |
68 | while (decompressedIndex < decompressedBarsCount && decompressedBars[decompressedIndex].Date < nextCompressedDate)
69 | compressedResult += getValueFunc(decompressedIndex++);
70 |
71 | results[compressedIndex] = compressedResult;
72 | }
73 | compressedResult = 0;
74 | while (decompressedIndex < decompressedBarsCount)
75 | compressedResult += getValueFunc(decompressedIndex++);
76 |
77 | results[lastCompressedIndex] = compressedResult;
78 | }
79 | return results;
80 | }
81 |
82 | private Func GetValueFunc(ISecurity security)
83 | {
84 | var tradeHistogramsCache = TradeHistogramsCaches.Instance.GetTradeHistogramsCache(Context, security, 0);
85 | var lotSize = security.LotSize;
86 |
87 | switch (QuantityMode)
88 | {
89 | case QuantityMode.Quantity:
90 | return index => GetValue(tradeHistogramsCache.GetHistogram(index));
91 | case QuantityMode.QuantityInLots:
92 | return index => GetValue(tradeHistogramsCache.GetHistogram(index)) / lotSize;
93 | default:
94 | return index => GetCount(tradeHistogramsCache.GetHistogram(index));
95 | }
96 | }
97 |
98 | protected abstract double GetValue(ICachedTradeHistogram histogram);
99 |
100 | protected abstract int GetCount(ICachedTradeHistogram histogram);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/VolumeAnalysis/SellsHandler.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using TSLab.Script.Handlers.Options;
3 |
4 | namespace TSLab.Script.Handlers
5 | {
6 | [HandlerCategory(HandlerCategories.VolumeAnalysis)]
7 | [HelperName("Sells", Language = Constants.En)]
8 | [HelperName("Продажи", Language = Constants.Ru)]
9 | [InputsCount(1)]
10 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
11 | [OutputsCount(1)]
12 | [OutputType(TemplateTypes.DOUBLE)]
13 | [Description("Показывает характеристики (количество или суммарный объем) сделок на продажу")]
14 | [HelperDescription("A handler calculates statistics (amount or total volume) of a short trades", Constants.En)]
15 | public sealed class SellsHandler : BuysSellsHandler
16 | {
17 | protected override double GetValue(ICachedTradeHistogram histogram)
18 | {
19 | return histogram.BidQuantity;
20 | }
21 |
22 | protected override int GetCount(ICachedTradeHistogram histogram)
23 | {
24 | return histogram.BidTradesCount;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/VolumeAnalysis/VolumeForPeriodHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | using TSLab.Script.Handlers.Options;
5 |
6 | namespace TSLab.Script.Handlers
7 | {
8 | [HandlerCategory(HandlerCategories.VolumeAnalysis)]
9 | [HelperName("Volume for period", Language = Constants.En)]
10 | [HelperName("Объём за период", Language = Constants.Ru)]
11 | [InputsCount(1)]
12 | [Input(0, TemplateTypes.SECURITY, Name = Constants.SecuritySource)]
13 | [OutputsCount(1)]
14 | [OutputType(TemplateTypes.DOUBLE)]
15 | [Description("Объём за период (суммарный или средний)")]
16 | [HelperDescription("Volume for period (total or average)", Constants.En)]
17 | public sealed class VolumeForPeriodHandler : ValueForPeriodHandler
18 | {
19 | protected override double GetValue(ISecurity security, int barIndex)
20 | {
21 | return security.Bars[barIndex].Volume;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------