Skip to content

Instantly share code, notes, and snippets.

@dirkolbrich
Created June 20, 2018 13:40
Show Gist options
  • Save dirkolbrich/4067ecb573a5eb693aa0b6e9330bb528 to your computer and use it in GitHub Desktop.
Save dirkolbrich/4067ecb573a5eb693aa0b6e9330bb528 to your computer and use it in GitHub Desktop.
concept of an algorithm tree - test in the playground https://play.golang.org/p/1fV78iCy_71
// This package demonstrates a concept of a strategy/asset tree, where each
// strategy has an algorythm stack. Each strategy can have different child strategies or assets.
package main
import (
"fmt"
)
// NodeHandler defines the basic node functionality.
type NodeHandler interface {
Name() string
SetName(string) NodeHandler
Parent() NodeHandler
SetParent(NodeHandler) NodeHandler
Children() []NodeHandler
SetChildren(...NodeHandler) NodeHandler
IsRoot() bool
IsChild() bool
Run()
}
// Node implements NodeHandler. It represents the base information of each tree node.
// This is the main building block of the tree.
type Node struct {
name string
parent NodeHandler
children []NodeHandler
}
// Name returns the name of Node
func (n Node) Name() string {
return n.name
}
// SetName sets the name of Node
func (n *Node) SetName(s string) NodeHandler {
n.name = s
return n
}
// Parent return the parent of this Node
func (n Node) Parent() NodeHandler {
return n.parent
}
// SetParent sets the parent of this Node
func (n *Node) SetParent(p NodeHandler) NodeHandler {
n.parent = p
return n
}
// Children returns the children of this Node
func (n Node) Children() []NodeHandler {
return n.children
}
// SetChildren sets the Children of this Node
func (n *Node) SetChildren(children ...NodeHandler) NodeHandler {
for _, child := range children {
child.SetParent(n)
}
n.children = children
return n
}
// IsRoot checks if this Node is a root node
func (n Node) IsRoot() bool {
if n.parent != nil {
return false
}
return true
}
// IsChild checks if this Node is a child of another node
func (n Node) IsChild() bool {
if n.parent == nil {
return false
}
return true
}
// Run is an empty function to satisfy the interface
func (n Node) Run() {}
// Strategy implements a sub node, used as a strategy building block
type Strategy struct {
Node
algos []Algo
}
// NewStrategy return a new strategy node ready to use
func NewStrategy(name string) *Strategy {
var s = &Strategy{}
s.SetName(name)
return s
}
// SetAlgo sets the algo stack for the Strategy
func (s *Strategy) SetAlgo(algos ...Algo) *Strategy {
for _, algo := range algos {
s.algos = append(s.algos, algo)
}
return s
}
// Run the algos of this Strategy Node, overwrite base Node method functionality
func (s Strategy) Run() {
// run algos
for _, algo := range s.algos {
if !algo.Run() {
return
}
}
// check for children and run their algos
for _, child := range s.Children() {
child.Run()
}
}
// Asset is a data building block, eg. Stock, Option, Cash etc
type Asset struct {
Node
}
// NewAsset return a new strategy node ready to use
func NewAsset(name string) *Asset {
var a = &Asset{}
a.SetName(name)
return a
}
// Children is an nil return, an Asset is not allowed to have children
func (a Asset) Children() []NodeHandler {
return []NodeHandler{}
}
// SetChildren does nothing, as an Asset ist not allowed to have children.
func (a *Asset) SetChildren(c ...NodeHandler) NodeHandler {
return a
}
// Algo defines the base algorythm functionality
type Algo interface {
Run() bool
}
// BasicAlgo is a base Algo which always returns true
type BasicAlgo struct {
}
// Run runs the algo
func (a BasicAlgo) Run() bool {
fmt.Println("running basic algo, return true")
return true
}
// FailAlgo is an algo which always fails
type FailAlgo struct {
}
// Run runs the algo
func (a FailAlgo) Run() bool {
fmt.Println("failing algo, return false")
return false
}
// NeverAlgo is an Algo which never gets called
type NeverAlgo struct {
}
// Run runs the algo
func (a NeverAlgo) Run() bool {
fmt.Println("never running algo, should return true")
return true
}
func main() {
// define main strategy
main := NewStrategy("main").SetAlgo(
BasicAlgo{},
)
// define second strategy
sec := NewStrategy("sec").SetAlgo(
// define an algo stack
BasicAlgo{},
FailAlgo{},
NeverAlgo{},
)
// define the tree from the bottom up
sec.SetChildren(
NewAsset("DBK.DE"),
)
main.SetChildren(
sec,
NewAsset("TEST.DE"),
NewAsset("BAS.DE"),
)
fmt.Printf("main: %+v\n", main)
fmt.Printf("main parent: %+v\n", main.Parent())
fmt.Printf("main is root: %+v\n", main.IsRoot())
fmt.Printf("main children:%+v\n", main.Children())
for _, child := range main.Children() {
fmt.Printf("child: %v, with parent: %v, is child: %+v\n", child.Name(), child.Parent().Name(), child.IsChild())
}
fmt.Printf("sec: %+v\n", sec)
fmt.Printf("sec parent: %+v\n", sec.Parent())
main.Run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment