Table of Contents

Создание индикатора

Создание собственного индикатора в API описано в пункте Собственный индикатор. Такие индикаторы полностью совместимы с Дизайнер.

Чтобы создать индикатор, на панели Схемы необходимо выбрать папку Индикаторы, нажать правую кнопку мыши и в контекстном меню выбрать Добавить:

Designer_Source_Code_Indicator_00

Код индикатора будет выглядеть так:

/// <summary>
/// Sample indicator demonstrating how to save and load parameters.
/// Changes the input price by +20% or -20%.
///
/// See more examples:
/// https://github.com/StockSharp/StockSharp/tree/master/Algo/Indicators
///
/// Documentation:
/// https://doc.stocksharp.com/topics/designer/strategies/using_code/fsharp/create_own_indicator.html
/// </summary>
type EmptyIndicator() as this =
	inherit BaseIndicator()

	// Internal fields
	let mutable changeValue = 20
	let mutable counter = 0
	let mutable isFormedValue = false

	/// <summary>
	/// The percentage value (+/-) used to modify the input price.
	/// </summary>
	member this.Change
		with get () = changeValue
		and set value =
			changeValue <- value
			this.Reset()

	/// <summary>
	/// Defines if the indicator has formed (became ready for trading).
	/// </summary>
	override this.CalcIsFormed() = isFormedValue

	/// <summary>
	/// Resets the indicator to its initial state.
	/// </summary>
	override this.Reset() =
		base.Reset()
		isFormedValue <- false
		counter <- 0

	/// <summary>
	/// The main logic to process input values.
	/// </summary>
	override this.OnProcess(input: IIndicatorValue) : IIndicatorValue =
		// every 10th call try to return an "empty" value
		if RandomGen.GetInt(0, 10) = 0 then
			// empty value still contains just time, no actual data
			DecimalIndicatorValue(this, input.Time)
		else
			// increment counter on each call
			counter <- counter + 1

			// after 5 inputs, indicator is considered formed
			if counter = 5 then
				isFormedValue <- true

			let mutable value = input.ToDecimal()

			// random change by a factor of +/- Change%
			let randomFactor = decimal (RandomGen.GetInt(-changeValue, changeValue)) / 100m
			value <- value + (value * randomFactor)

			// return final indicator value
			let result = DecimalIndicatorValue(this, value, input.Time)
			// randomly mark it as final or not
			result.IsFinal <- RandomGen.GetBool()
			result

	/// <summary>
	/// Load indicator settings from a given <see cref="SettingsStorage"/>.
	/// </summary>
	override this.Load(storage: SettingsStorage) =
		base.Load(storage)
		this.Change <- storage.GetValue<int>(nameof(this.Change))

	/// <summary>
	/// Save indicator settings to a given <see cref="SettingsStorage"/>.
	/// </summary>
	override this.Save(storage: SettingsStorage) =
		base.Save(storage)
		storage.SetValue(nameof(this.Change), this.Change)

	/// <summary>
	/// A string representation that includes the current <see cref="Change"/> value.
	/// </summary>
	override this.ToString() =
		sprintf "Change: %d" this.Change

Данный индикатор получает входящее значение и делает у него произвольное отклонение на значение, заданное параметром Change.

Описание методов индикатора доступно в разделе Собственный индикатор.

Чтобы добавить созданный индикатор на схему, необходимо использовать кубик Индикатор, и уже в нем задать необходимый индикатор:

Designer_Source_Code_Indicator_01

Параметр Change, ранее заданный в коде индикатора, показан в панели свойств.

Warning

Индикаторы из F# кода невозможно использовать в стратегиях, созданных на F# коде. Их возможно использовать только в стратегиях, созданных из кубиков.