Criar o seu próprio cubo

De forma semelhante à criação de um cubo a partir de um esquema, pode criar o seu próprio cubo com base em código Python. Um cubo deste tipo será mais funcional do que um cubo criado a partir de um esquema.

Para criar um cubo a partir de código, tem de o criar na pasta Blocos personalizados:

Designer_Source_Code_Elem_00

No exemplo abaixo, o cubo herda da classe DiagramExternalElement e tem o seguinte aspeto:

import clr

# Adicionar referências aos assemblies StockSharp necessários
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Diagram.Core")

# Importar os tipos necessários de .NET e StockSharp
from System import Action
from StockSharp.Messages import Unit
from StockSharp.Messages import ICandleMessage
from StockSharp.Diagram import DiagramExternalElement

from designer_extensions import diagram_external

# Classe de elemento de diagrama personalizada que demonstra a utilização de sockets de entrada e saída
class empty_diagram_element(DiagramExternalElement):
	"""
	Exemplo de elemento de diagrama que demonstra a utilização de sockets de entrada e saída.

	https://doc.stocksharp.com/topics/designer/strategies/using_code/python/creating_your_own_cube.html
	"""

	def __init__(self):
		super(empty_diagram_element, self).__init__()

		# Propriedade de exemplo para mostrar como adicionar parâmetros ao elemento de diagrama
		# Este parâmetro chama-se "MinValue" e tem o valor predefinido 10
		self._minValue = self.AddParam("MinValue", 10)\
							.SetBasic(True)\
							.SetDisplay("Parâmetros", "Valor mínimo", "Descrição do parâmetro de valor mínimo", 10)

		# Inicializar os manipuladores de eventos de saída como listas vazias
		# Os subscritores podem atribuir métodos chamáveis a estes manipuladores
		self._output1_handlers = []
		self._output2_handlers = []

	# Os sockets de saída são eventos assinalados com o atributo DiagramExternal

	@diagram_external
	def add_Output1(self, handler: Action[Unit]):
		"""
		Subscrever o evento Output1.

		:param handler: Um método chamável a invocar quando Output1 é acionado.
		"""
		self._output1_handlers.append(handler)

	def remove_Output1(self, handler):
		"""
		Anular a subscrição do evento Output1.

		:param handler: O método chamável a remover dos subscritores de Output1.
		"""
		if handler in self._output1_handlers:
			self._output1_handlers.remove(handler)

	@diagram_external
	def add_Output2(self, handler: Action[Unit]):
		"""
		Subscrever o evento Output2.

		:param handler: Um método chamável a invocar quando Output2 é acionado.
		"""
		self._output2_handlers.append(handler)

	def remove_Output2(self, handler):
		"""
		Anular a subscrição do evento Output2.

		:param handler: O método chamável a remover dos subscritores de Output2.
		"""
		if handler in self._output2_handlers:
			self._output2_handlers.remove(handler)

	# Descomente a propriedade seguinte se quiser que o método Process
	# seja chamado sempre que for recebido um novo argumento
	# (não é necessário esperar pela receção de todos os argumentos de entrada).
	#
	# @property
	# def WaitAllInput(self):
	#     return False

	@diagram_external
	def Process(self, candle: ICandleMessage, diff: Unit) -> None:
		"""
		Os sockets de entrada são parâmetros de métodos assinalados com o atributo DiagramExternal.
		Processa uma vela e um valor diff e, em seguida, invoca eventos de saída com base na lógica.

		:param candle: Entrada CandleMessage que representa uma vela.
		:param diff: Unit que representa o valor de diferença a processar.
		"""
		# Calcular o resultado como a soma do preço de fecho da vela e do valor diff
		res = candle.ClosePrice + diff

		# Invocar Output1 se diff for maior ou igual ao parâmetro MinValue,
		# caso contrário, invocar Output2
		if diff >= self._minValue.Value:
			for handler in self._output1_handlers:
				handler(res)
		else:
			for handler in self._output2_handlers:
				handler(res)

	def Start(self):
		"""
		Chamado quando o elemento de diagrama é iniciado. Adicione aqui qualquer lógica anterior ao início.
		"""
		super(empty_diagram_element, self).Start()
		# Adicionar lógica personalizada a executar antes de o elemento iniciar

	def Stop(self):
		"""
		Chamado quando o elemento de diagrama é parado. Adicione aqui qualquer lógica posterior à paragem.
		"""
		super(empty_diagram_element, self).Stop()
		# Adicionar lógica personalizada a executar depois de o elemento parar

	def Reset(self):
		"""
		Chamado quando o elemento de diagrama é reposto. Adicione aqui qualquer lógica de reposição.
		"""
		super(empty_diagram_element, self).Reset()
		# Adicionar lógica personalizada para repor o estado interno do elemento

Neste código, o cubo tem dois sockets de entrada e dois sockets de saída. Os sockets de entrada são definidos aplicando o decorador @diagram_external a um método:

@diagram_external
def Process(self, candle: ICandleMessage, diff: Unit) -> None:

Os sockets de saída são definidos aplicando o decorador @diagram_external a um evento (operação de subscrição de evento add_NNN). No exemplo do cubo, existem dois eventos deste tipo:

# Os sockets de saída são eventos assinalados com o atributo DiagramExternal

@diagram_external
def add_Output1(self, handler: Action[Unit]):
	"""
	Subscrever o evento Output1.

	:param handler: Um método chamável a invocar quando Output1 é acionado.
	"""
	self._output1_handlers.append(handler)

def remove_Output1(self, handler):
	"""
	Anular a subscrição do evento Output1.

	:param handler: O método chamável a remover dos subscritores de Output1.
	"""
	if handler in self._output1_handlers:
		self._output1_handlers.remove(handler)

@diagram_external
def add_Output2(self, handler: Action[Unit]):
	"""
	Subscrever o evento Output2.

	:param handler: Um método chamável a invocar quando Output2 é acionado.
	"""
	self._output2_handlers.append(handler)

def remove_Output2(self, handler):
	"""
	Anular a subscrição do evento Output2.

	:param handler: O método chamável a remover dos subscritores de Output2.
	"""
	if handler in self._output2_handlers:
		self._output2_handlers.remove(handler)

Assim, também existirão dois sockets de saída.

Além disso, é mostrado como criar uma propriedade para o cubo:

self._minValue = self.AddParam("MinValue", 10)\
					.SetBasic(True)\
					.SetDisplay("Parâmetros", "Valor mínimo", "Descrição do parâmetro de valor mínimo", 10)

Ao utilizar a classe DiagramElementParam, a abordagem de guardar e restaurar definições é usada automaticamente.

A propriedade Valor mínimo está marcada como básica e ficará visível no modo Definições básicas.

A propriedade comentada WaitAllInput determina quando é chamado o método com sockets de entrada:

# @property
# def WaitAllInput(self):
#     return False

Se descomentar a propriedade, o método Processo será chamado sempre que chegar pelo menos um valor (no caso do exemplo, uma vela ou um valor numérico).

Para adicionar o cubo resultante ao esquema, tem de selecionar o cubo criado na paleta, na secção Blocos personalizados:

Designer_Source_Code_Elem_01

Warning

Cubos criados a partir de código Python não podem ser usados em estratégias criadas em código Python. Só podem ser usados em estratégias criadas a partir de cubos.

Ver Também

Criar um indicador