Создание собственного кубика

Аналогично созданию кубика из схемы можно создать свой кубик на основе F# кода. Такой кубик будет более функциональным, чем кубик из схемы.

Для создания кубика из кода, необходимо создать его в папке Собственные кубики:

Designer_Source_Code_Elem_00

В нижеприведённом примере кубик наследуется от класса DiagramExternalElement и выглядит следующим образом:

/// <summary>
/// Пример элемента диаграммы показывает использование входных и выходных сокетов.
///
/// Подробнее:
/// https://doc.stocksharp.com/topics/designer/strategies/using_code/fsharp/creating_your_own_cube.html
/// </summary>
type EmptyDiagramElement() as this =
	inherit DiagramExternalElement()

	// Пример свойства, показывающий создание параметров
	let minValueParam =
		this.AddParam<int>("MinValue", 10)
			.SetBasic(true)  // make the parameter visible in basic mode
			.SetDisplay("Parameters", "Min value", "Min value parameter description", 10)

	// Выходные сокеты — это события, помеченные атрибутом DiagramExternal
	let output1Event = new Event<Unit>()
	let output2Event = new Event<Unit>()

	[<CLIEvent>]
	[<DiagramExternal>]
	member this.Output1 = output1Event.Publish

	[<CLIEvent>]
	[<DiagramExternal>]
	member this.Output2 = output2Event.Publish

	// Раскомментируйте следующее свойство, если хотите, чтобы метод Process 
	// вызывался каждый раз при получении нового аргумента
	// (no need to wait for all input args to be received).
	//
	// переопределить this.WaitAllInput
	//     with get () = false

	// Входные сокеты — это параметры методов, помеченные атрибутом DiagramExternal

	[<DiagramExternal>]
	member this.Process(candle: CandleMessage, diff: Unit) =
		let res = candle.ClosePrice + diff

		if diff >= minValueParam.Value then
			// Вызвать первое выходное событие
			output1Event.Trigger(res)
		else
			// Вызвать второе выходное событие
			output2Event.Trigger(res)

	override this.Start() =
		base.Start()
		// При необходимости добавить логику перед запуском

	override this.Stop() =
		base.Stop()
		// При необходимости добавить логику после остановки

	override this.Reset() =
		base.Reset()
		// При необходимости добавить логику сброса внутреннего состояния

В данном коде кубик имеет два входящих сокета и два исходящих. Входящие сокеты определяются путем применения атрибута DiagramExternalAttribute к методу:

[<DiagramExternal>]
member this.Process(candle: CandleMessage, diff: Unit) =

Исходящие сокеты определяются путем применения атрибута к событию. В примере кубика таких событий два:

// Выходные сокеты — это события, помеченные атрибутом DiagramExternal
let output1Event = new Event<Unit>()
let output2Event = new Event<Unit>()

[<CLIEvent>]
[<DiagramExternal>]
member this.Output1 = output1Event.Publish

[<CLIEvent>]
[<DiagramExternal>]
member this.Output2 = output2Event.Publish

Поэтому исходящих сокетов также будет два.

Дополнительно показано как сделать свойство у кубика:

// Пример свойства, показывающий создание параметров
let minValueParam =
	this.AddParam<int>("MinValue", 10)
		.SetBasic(true)  // make the parameter visible in basic mode
		.SetDisplay("Parameters", "Min value", "Min value parameter description", 10)

При использовании класса DiagramElementParam автоматически используется подход сохранения и восстановления настроек.

Свойство MinValue помечено как basic, и оно будет видно в режиме Базовые свойства.

Закомментированное свойство WaitAllInput отвечает за время вызова метода со входящими сокетами:

// переопределить this.WaitAllInput
//     with get () = false

Если раскомментировать свойство, то метод Process будет вызываться всегда, как только придёт хотя бы одно значение (в случае примера это или свеча, или числовое значение).

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

Designer_Source_Code_Elem_01

Warning

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

См. также

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