建模杂谈系列237 使用FSM进行状态管理

news2024/12/27 13:42:41

说明

使用FSM来对状态的变化进行管理,一方面有助于我们将问题定义的更清晰,同时也让程序设计更可靠、可读性(事后)更强。

内容

1 问题描述

假设有一笔投资用于证券交易,随着交易、市场价格变化,投资的状态也随之改变。我们需要了解并定义这些状态,以便设计策略长期执行。

一般我们关心投资的盈亏,而这些与是否持仓相关,如果持仓的话又与价格涨跌有关。假设我们暂时不管决策,那么可以先定义以下一些状态:
Init: 初始化
Stop:停止
EB: Empty Breakeven 空仓(盈亏)平衡
HB: Hold Breakeven 持仓(盈亏)平衡
HW1: Hold Win 1 持仓盈利-小幅
HW2: Hold Win 2 持仓盈利-大幅
EW1: Empty Win1 空仓盈利-小幅
EW2: Empty Win2 空仓盈利-大幅
HL1: Hold Loss 1 持仓亏损-小幅
HL2: Hold Loss2 持仓亏损-大幅
EL1: Empty Loss 1 空仓亏损-小幅
EL2: Empty Loss 1 空仓亏损-大幅

事件:

  • 1 涨跌 up / down (相对于期初资产)
  • 2 买卖 buy / sell
  • 3 控制停止 control stop(输赢都可能被控制停止)
  • 4 初始化: init 重新按照参数初始化实例
  • 5 无变化 unchange

以上有一个假设:在一个时隙(一分钟内)不可能会出现资产的大幅波动。如果出现意外情况(try…except),程序将根据资产盈利、订单持有状态将对象的状态直接置为对应值。
在这里插入图片描述

2 代码实验

用代码实现如下:

状态为包含Init和Stop在内的十二个状态,事件则为unchange, up,down, buy,sell以及stop和init 等六种。

其中unchange和stop是对所有状态都生效的。stop本来分为正常停止以及手动停止的,但是总体上都可以归于stop。

class BT2:
    pass

# 12个状态
states = ['Init','EB','HB','HW1','HW2','EW1','EW2','HL1','HL2','EL1','EL2','Stop']
transitions = [
    # unchange事件
    {'trigger': 'unchange', 'source': 'Init', 'dest': 'EB'},
    {'trigger': 'unchange', 'source': 'EB', 'dest': 'EB'},
    {'trigger': 'unchange', 'source': 'HB', 'dest': 'HB'},
    {'trigger': 'unchange', 'source': 'HW1', 'dest': 'HW1'},
    {'trigger': 'unchange', 'source': 'HW2', 'dest': 'HW2'},
    {'trigger': 'unchange', 'source': 'EW1', 'dest': 'EW1'},
    {'trigger': 'unchange', 'source': 'EW2', 'dest': 'EW2'},
    {'trigger': 'unchange', 'source': 'HL1', 'dest': 'HL1'},
    {'trigger': 'unchange', 'source': 'HL2', 'dest': 'HL2'},
    {'trigger': 'unchange', 'source': 'EL1', 'dest': 'EL1'},
    {'trigger': 'unchange', 'source': 'EL2', 'dest': 'EL2'},
    # up事件:比上一个level高3个点, Init有一个InitCap,约定 B_center = InitCap,  B的Band定为3个点, B+3pt =  W1的下界以此类推
    {'trigger': 'up', 'source': 'Init', 'dest': 'EB'},
    # up对E无影响
    {'trigger': 'up', 'source': 'EB', 'dest': 'EB'},
    {'trigger': 'up', 'source': 'EW1', 'dest': 'EW1'},
    {'trigger': 'up', 'source': 'EW2', 'dest': 'EW2'},
    {'trigger': 'up', 'source': 'EL1', 'dest': 'EL1'},
    {'trigger': 'up', 'source': 'EL2', 'dest': 'EL2'},
    # up对H有影响
    {'trigger': 'up', 'source': 'HB', 'dest': 'HW1'},
    {'trigger': 'up', 'source': 'HW1', 'dest': 'HW2'},
    {'trigger': 'up', 'source': 'HW2', 'dest': 'Stop'},
    {'trigger': 'up', 'source': 'HL1', 'dest': 'HB'},
    {'trigger': 'up', 'source': 'HL2', 'dest': 'HL1'},    
    
    
    # down事件:类似up事件
    {'trigger': 'down', 'source': 'Init', 'dest': 'EB'},
    
    {'trigger': 'down', 'source': 'EB', 'dest': 'EB'},
    {'trigger': 'down', 'source': 'EW1', 'dest': 'EW1'},
    {'trigger': 'down', 'source': 'EW2', 'dest': 'EW2'},
    {'trigger': 'down', 'source': 'EL1', 'dest': 'EL1'},
    {'trigger': 'down', 'source': 'EL2', 'dest': 'EL2'},
    # down对H有影响
    {'trigger': 'down', 'source': 'HB', 'dest': 'HL1'},
    {'trigger': 'down', 'source': 'HW1', 'dest': 'HB'},
    {'trigger': 'down', 'source': 'HW2', 'dest': 'HW1'},
    {'trigger': 'down', 'source': 'HL1', 'dest': 'EL2'},
    {'trigger': 'down', 'source': 'HL2', 'dest': 'Stop'},    
    
    # buy事件,仅对E类生效
    {'trigger': 'buy', 'source': 'EB', 'dest': 'HB'},
    {'trigger': 'buy', 'source': 'EW1', 'dest': 'HW1'},
    {'trigger': 'buy', 'source': 'EW2', 'dest': 'HW2'},
    {'trigger': 'buy', 'source': 'EL1', 'dest': 'HL1'},
    {'trigger': 'buy', 'source': 'EL2', 'dest': 'HL2'},
    # sell事件,仅对H类生效
    {'trigger': 'sell', 'source': 'HB', 'dest': 'EB'},
    {'trigger': 'sell', 'source': 'HW1', 'dest': 'EW1'},
    {'trigger': 'sell', 'source': 'HW2', 'dest': 'EW2'},
    {'trigger': 'sell', 'source': 'HL1', 'dest': 'EL1'},
    {'trigger': 'sell', 'source': 'HL2', 'dest': 'EL2'}, 
    # stop事件
    {'trigger': 'stop', 'source': 'Init', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'HB', 'dest': 'Stop'}, 
    {'trigger': 'stop', 'source': 'HL1', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'HL2', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'HW1', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'HW2', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'EB', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'EL1', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'EL2', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'EW1', 'dest': 'Stop'},
    {'trigger': 'stop', 'source': 'EW2', 'dest': 'Stop'},
    # init事件
    {'trigger': 'init', 'source': 'Stop', 'dest': 'Init'},
    
    
]
# 创建状态机
machine = Machine(model=BT2, states=states, transitions=transitions, initial='Init')

然后进行测试

import random

# 定义状态机事件列表
events = ['unchange', 'up', 'down', 'buy', 'sell']

# 生成随机事件列表
random_events = [random.choice(events) for _ in range(10)]  # 生成包含10个随机事件的列表
print(random_events)

['sell', 'unchange', 'sell', 'buy', 'unchange', 'unchange', 'up', 'unchange', 'sell', 'unchange']

bt2_instance = BT2()
for i,event in  enumerate(random_events):
    print('>>>>>>> %s >>>>>' %i)
    print(bt2_instance.state)
    try:
        bt2_instance.trigger(event)
        print(bt2_instance.state)
    except:
        print(' conflicts ' ,bt2_instance.state, ' vs ' ,event)

>>>>>>> 0 >>>>>
Init
 conflicts  Init  vs  sell
>>>>>>> 1 >>>>>
Init
EB
>>>>>>> 2 >>>>>
EB
 conflicts  EB  vs  sell
>>>>>>> 3 >>>>>
EB
HB
>>>>>>> 4 >>>>>
HB
HB
>>>>>>> 5 >>>>>
HB
HB
>>>>>>> 6 >>>>>
HB
HW1
>>>>>>> 7 >>>>>
HW1
HW1
>>>>>>> 8 >>>>>
HW1
EW1
>>>>>>> 9 >>>>>
EW1
EW1

可以看到,正常情况下,合法的状态转移都是ok的;而未定义的转移则会报错。

3 总结

带来的好处:

清晰化

这部分的好处是体现在代码之前的。能够设定目标问题的状态及其变化,首先就需要思考及明确其中的关键因素,而这些可能是在开始时没有想好的。

例如,有哪些状态是基本的,有哪些是对业务有帮助的。在整个运行过程中,可能会有哪些变化(事件),这些事件又会如何转变当前实例的状态。以及,有哪些不合法的事件:在状态A下不可能发生某些事件。

在代码的运行过程中,每次的执行,总是能够被简单且清晰的记录下来。即便在事后,也可以很容易的通过这些状态记录,对问题进行快速的分析。

结构化

在定义了状态之后,很显然就会对方法进行区分。例如 processing这个方法,在状态A和状态B下显然是不同的,可以针对每一个状态都单独的写(当然也可以复用部分通用的)。这样processing 实际上是按状态区分的。

从图的角度来说,FSM实际上是一个规模较小的子图,在执行的过程中不断进行(循环)游历。它强调了图结构,以及重复执行图。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1508067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

巫蛊之祸——汉武帝后期的一次重大事件

引 言 “巫蛊之祸”是汉武帝在位后期发生的一次重大政治事件,也是西汉历史上最大的冤案,此案导致皇后卫子夫和太子刘据自杀,数万人头落地,几十万人被牵连。 一、巫蛊之术的由来 《汉书》记载,巫蛊之术起源自胡巫&am…

解决Iterm2升级后遇到“Stashed changes“的问题

<<<<<<< Updated upstream ...... >>>>>>> Stashed changes冲突标记符的代码如题,最近有升级Item2…

ROS的消息发布者与订阅者示例

前言 Topic话题,是节点之间信息交换的方法,在向话题发生送消息的节点叫做发布者,接收消息的节点叫做订阅者。 一个ROS程序中话题可以有很多个,一个话题中也可以有多个发布者和订阅者。一个订阅者可以订阅多个话题。同样 &#xff…

Linux 地址空间

目录 一、程序地址空间 1、虚拟地址 Makefile新写法 2、进程地址空间分布 3、栈&堆 4、static修饰局部变量 5、字符串常量不可修改 6、虚拟地址与物理地址的联系 二、CPU读取程序全过程 1、形成可执行程序 2、生成虚拟地址 3、程序的启动 4、创建进程 5、地…

MyBatis-Plus生成sql语句时怎么知道表名和表的字段名,表的主键名的

MyBatis-Plus通过反射获取实体类的信息。 实体类的类名驼峰转下划线为表名 实体类的属性名驼峰转下划线为字段名 表的主键名默认为id selectById就是基于这个id,select 查询字段 from user where id ? 自定义告诉mybatisplus数据库的表名&#xff0c…

SpringMVC10、拦截器

10、拦截器 10.1、概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。 过滤器与拦截器的区别:拦截器是AOP思想的具体应用。 过滤器 servlet规范中的一部分&…

AWS Database Migration Service 助力数据库搬迁

在业务出海的过程中,少不了的就是云迁移,但在云迁移的过程中其中最重要的一环就是数据库。通常迁移的成功就取决于数据,如果应用成功搬迁,数据库没过来也是无用功。因此如何快速、安全的进行数据库搬迁也成为一大难题。九河云公司…

8.5 Springboot项目实战 Redis缓存热点数据

文章目录 前言一、缓存与数据库一致性二、Repository层 -- Cache Aside模式实操BookRepositoryBookRepositoryImpl2.1 查询2.2 修改2.3 删除2.4 扩展Mapper修改三、Service层调用修改四、测试前言 前两文我们讲解了如何在SpringBoot中整合Redis,接下来我们将进行

智慧水务大数据,信息化云平台建设,综合运营管理平台

一、水务信息化的建设方向 1、完善基础设施构建软件定义的数据中心 基础设施,建设新一代软件定义的数据中心;逐步整合水务和海洋资源、统一、规范化各业务系统,按照一体化、一站式的服务进行建设。 2、整合信息资源建立智慧决策体系 统一信息采集方式,…

STM32CubeIDE基础学习-STM32CubeIDE软件工程文件拷贝粘贴

STM32CubeIDE基础学习-STM32CubeIDE软件工程文件拷贝粘贴 前言 在后面开发程序时,往往不需要再重新新建工程的了,可以直接在原有的工程基础上直接复制粘贴新增功能就可以了。 具体的操作方法步骤如下介绍: 第一步:找到一个原有的…

中医中的虚是什么?虚的分类?如何治疗气虚?

目录 中医中虚的分类气虚(此处指脾气虚)症状舌象:舌头中间区域有裂痕 或者 舌胖有齿痕身体上 解决方法其它脏腑气虚的情况及解决方法 血虚津液不足阴虚阳虚 中医中虚的分类 图片来源于微信视频的名为 路广林主任 的视频。 气虚(此…

九州金榜|孩子厌学怎么引导?

孩子在成长的过程中,尤其在上学的时候,孩子出现厌学情绪这是非常常见的事情,当孩子出现厌学情绪时,家长要采取什么样的方法才能帮助孩子找回学习兴趣和动力呢?九州金榜家庭教育给出建议,首先父母不应该过于…

代码随想录day17(3)二叉树:二叉树的中序遍历(leetcode94)

题目要求:实现二叉树的中序遍历。 思路:对于二叉树的中序遍历,通常可以使用递归算法与非递归(迭代)算法两种。 对于递归算法的处理与前序、后序基本相同,只是本次应先访问其左节点,然后进行pu…

计算机网络—以太网接口和链路配置

目录 1.拓扑图 2.以太网交换机基础配置 3.配置手动模式的链路聚合 4.配置静态 LACP 模式的链路聚合 5.配置文件 1.拓扑图 2.以太网交换机基础配置 华为交换机接口默认开启了自协商功能,需要手动配置S1与 S2上G0/0/9和G0/0/10接口的速率。 首先修改交换机的设…

【力扣100】【好题】322.零钱兑换 || 01背包完全背包

添加链接描述 思路: dp[j]数组表示的是在金额达到 j 的时候所需要的最小硬币数金额:背包容量,每个硬币的个数都为1:背包中物品的价值,硬币面额:物品重量dp[j]min(dp[j],dp[j-coin]1) class Solution:def …

什么是智慧公厕?智慧公厕的应用价值有哪些?

在现代社会,城市的发展与人民生活质量息息相关。作为城市基础设施中的重要一环,公共厕所的建设及管理一直备受关注。智慧公厕作为一种公共厕所使用、运行、管理的综合应用解决方案,正逐渐在智慧城市的建设中崭露头角。那么,智慧公…

Flutter does not exist

Flutter does not exist 原因:Generated.config 配置文件内路径缺失 原因:Flutter SDK缺失 通过配置文件查到Flutter SDK在本地的存放位置FLUTTER_FRAMEWORK_DIR/Users/haijunyan/Documents/flutter/bin/cache/artifacts/engine/ios 真机所需&#xf…

11---数字温度 OR 湿度传感器电路设计

视频链接 数字温度or湿度传感器电路设计02_哔哩哔哩_bilibili 数字温度 OR 湿度传感器电路设计 1、温湿度传感器 DHT11 DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度-5%RH, 温度-2℃,量程湿度20-90%RH, 温度0~50℃。 D…

一、什么是 HarmonyOS ?

HarmonyOS 是华为开发的一款面向未来的全场景分布式智慧操作系统,将逐步覆盖 18N 全场景终端设备。 对消费者而言,HarmonyOS 用一个“统一的软件系统”,从根本上解决消费者面对大量智能终端体验割裂的问题,为消费者带来统一、便利…

使用OpenCV实现两张图像融合在一起

简单介绍 图像融合技术是一种结合多个不同来源或不同传感器捕获的同一场景的图像数据,以生成一幅更全面、更高质量的单一图像的过程。这种技术广泛应用于遥感、医学影像分析、计算机视觉等多个领域。常见的图像融合技术包括基于像素级、特征级和决策级的融合方法&a…