解决“如果发生地狱”的最佳方法是什么?

时间:2019-05-19 08:03:53

标签: python python-3.x oop design-patterns

我有一个Deal类,它具有多个状态:新建,已购买,已完成,趋势和交叉属性。交易实例可以随时更改趋势和交叉交易-取决于市场情况。

取决于当前的“趋势”,“交叉”以及其他可能发生的情况,可以采用不同的方式处理

我尝试了战略和责任链模式,但是我的知识和经验不足以正确地做到这一点。我不确定做出正确的决定。

现在它可以工作了,但这真是个ifs的地狱

async def check_deal(deal):

    if deal.is_new():
        if deal.current_trend == UP_TREND and CROSSED_TOP_GREEN in deal.crossing:
            return await deal.create_order(CROSSED_TOP_GREEN)

        if deal.current_trend == FLAT_TREND and CROSSED_BOTTOM_ORANGE in deal.crossing:
            return await deal.create_order(CROSSED_BOTTOM_ORANGE)

        if deal.current_trend == DOWN_TREND and CROSSED_BOTTOM in deal.crossing:
            return await deal.create_order(CROSSED_BOTTOM)

    if deal.is_bought() and not deal.candle_has_order:
        if deal.current_trend == UP_TREND and CROSSED_BOTTOM_GREEN in deal.crossing:
            return await deal.create_order(CROSSED_BOTTOM_GREEN)
        else:
            return await deal.update_deal()

        if deal.current_trend == DOWN_TREND and CROSSED_BOTTOM in deal.crossing:
            return await deal.create_order(CROSSED_BOTTOM)
        else:
            return await deal.update_deal()

    else:
        return await deal.update_deal()

    if deal.is_profitable() and len(deal.orders) == 1 :
        if deal.current_trend == UP_TREND  and CROSSED_TOP in deal.crossing:
            return await deal.trailing_enable(CROSSED_TOP)

        if deal.current_trend == FLAT_TREND and CROSSED_TOP_GREEN in deal.crossing:
            return await deal.trailing_enable(CROSSED_TOP_GREEN)

        if deal.current_trend == DOWN_TREND and CROSSED_BASIS in deal.crossing:
            return await deal.trailing_enable(CROSSED_BASIS)

    if deal.is_profitable() and len(deal.orders) > 1:
        if deal.current_trend == UP_TREND and CROSSED_BASIS in deal.crossing:
            return await deal.trailing_enable(CROSSED_BASIS)

        if deal.current_trend == DOWN_TREND and  CROSSED_BOTTOM_GREEN in deal.crossing:
            return await deal.trailing_enable(CROSSED_BOTTOM_GREEN)

规则

电流穿越是一个变量,可以随时不同 当前趋势是一个变量,随时都可能不同

我们在以下一种情况下开始交易:

  1. Deal.is_new()(交易未保存到数据库中),当前趋势为UP,当前交易在交易中。
  2. Deal.is_new(),当前趋势为FLAT,当前交叉为交易中。
  3. Deal.is_new(),当前趋势为下降,当前交易在交易中。

在以下情况之一中,我们将资金添加到当前交易中:

  1. Deal.is_bought()(交易已在数据库中),当前趋势为UP,当前交易为Deal.crossing
  2. Deal.is_bought()(交易在数据库中),当前趋势为下降,当前交易为交易中。

在以下情况之一中,我们通过交易获利:

  1. 交易有利可图,交易只有1个订单,当前趋势为UP,当前交易在交易中。
  2. 交易有利可图,交易只有1个订单,当前趋势为FLAT,当前交易为交易中。
  3. 交易有利可图,交易只有1个订单,当前趋势为下降,当前交易在交易中。
  4. 交易有利可图,交易有1个以上的订单,当前趋势为UP,当前交易在交易中。
  5. 交易有利可图,交易有超过1个订单,当前趋势为FLAT,当前交易在交易中。
  6. 交易有利可图,交易有超过1个订单,当前趋势为下降,当前交易在交易中。

如果不满足deal.is_bought()和其他任何条件,我们只会更新交易

4 个答案:

答案 0 :(得分:3)

这里的内容是:当满足条件时,需要执行动作

您可以定义一个接口(可以使用简单的基类或抽象基类)来捕获它。然后为各种 if -> action 添加添加实现此接口的类(从基类继承)。

这是一个例子:

class Rule:

    def isMetBy(self, deal):
        pass

    def execute(self, deal):
        pass

class Rule1(Rule):

    def isMetBy(self, deal):
        return deal.current_trend == FLAT_TREND and CROSSED_BOTTOM_ORANGE in deal.crossing

    async def execute(self, deal):
        return await deal.create_order(CROSSED_BOTTOM_ORANGE)

class Rule2(Rule):

    def isMetBy(self, deal):
        return deal.current_trend == DOWN_TREND and CROSSED_BOTTOM in deal.crossing

    async def execute(self, deal):
        return await deal.create_order(CROSSED_BOTTOM)

rules = [Rule1(), Rule2()]

async def check_deal(deal):

    for rule in rules:
        if(rule.isMetBy(deal)):
            return await rule.execute(deal)

每个规则捕获一个if语句就是您的代码。这样,您可以定义所需的任意多个规则。添加新类仅是添加另一个类的问题。如果可以的话,可以使用好名字为规则命名,这样可以增加好处或命名您的规则。我使用Rule1和Rule2是因为我不知道您的规则是什么意思。例如,您可以有类似的内容(我只是出于说明目的而编造的) EnableTrailingForProfitableDealsRule

在您的情况下,您有一个 if ,其中有多个 subif's 。您可以将它们分离为不同的类,也可以使用Composite pattern创建具有 子规则 规则 >。

这是一个例子:

class CompositeRule(Rule):
    subRules = []

    def __init(self):
        self.subRules = [Rule1(), Rule2()]

    def isMetBy(self, deal):

        if deal.is_profitable() and len(deal.orders) == 1 :
            for rule in self.subRules:
                if(rule.isMetBy(deal)):
                    return true;

        return false

    async def execute(self, deal);

        for rule in self.subRules:
            if(rule.isMetBy(deal)):
                return await rule.execute(deal)

CompositeRules可以使代码更容易理解。如果使用CompositeRules很难理解代码,则可以改用简单的规则。如果其中有成文法,这些简单规则中的许多规则将具有相同的含义,但这通常不是问题。

这是CompositeRule分解为两个简单的规则:

class Rule1(Rule):

    def isMetBy(self, deal):
        return if deal.is_profitable() and len(deal.orders) == 1 and deal.current_trend == UP_TREND  and CROSSED_TOP in deal.crossing

    async def execute(self, deal):
        return await deal.trailing_enable(CROSSED_TOP)

class Rule2(Rule):

    def isMetBy(self, deal):
        return if deal.is_profitable() and len(deal.orders) == 1 and  deal.current_trend == FLAT_TREND and CROSSED_TOP_GREEN in deal.crossing:

    async def execute(self, deal):
        return await deal.trailing_enable(CROSSED_TOP_GREEN)

您可以尝试并选择最适合自己的方法。

答案 1 :(得分:2)

代码复杂的一个原因是您以过程的方式处理对象check_deal正在检查交易的属性并基于决策在他们身上,然后调用交易的方法。这种逻辑属于Deal类,例如Deal.check方法。

将逻辑移到Deal类中并不会使其变得那么复杂,但是它为选择不同的设计开辟了道路。

例如,可以检查DealNewDealBoughtDeal的子类,而不用检查条件代码块中的FinishedDeal是新的还是购买的或完成的子类。 {1}}方法仅与影响这些特定类型的决策有关。

如果在您的应用程序中没有必要使用类型子类化,则策略模式可能是实现此目的的另一种方法-一个check类,但可以根据交易类型提供不同的检查策略。

另一种方法可能是将Deal的生命周期中的事件建模为状态机。创建代表生命周期各个阶段的Deal类,这些类知道要采取的适当操作以及如何决定下一个状态应该是什么(责任链在这里可能有用)。这可能需要仔细建模,以防止StateDeal之间的过度耦合。

简而言之,请尝试构建业务逻辑,以使您不必进行决策的类:它们只是做对了事,或者至少用最少的条件代码来做对事。

答案 2 :(得分:0)

  

现在它可以工作了,但这真是ifs的地狱。

您的if-逻辑有缺陷-您的代码无法访问

if deal.is_bought() and not deal.candle_has_order:
    if deal.current_trend == UP_TREND and CROSSED_BOTTOM_GREEN in deal.crossing:
        return await deal.create_order(CROSSED_BOTTOM_GREEN)
    else:
        return await deal.update_deal()

    # Neither of the following will EVER happen, you already 
    # left the function with the _else_ from above:
    if deal.current_trend == DOWN_TREND and CROSSED_BOTTOM in deal.crossing:
        return await deal.create_order(CROSSED_BOTTOM)
    else:
        return await deal.update_deal()
  

我尝试了战略和责任链模式,但是我的知识   并且经验不足以正确地做到这一点。我不确定   做出了正确的决定。

在不知道您的规则是什么的情况下,我们有点无法提供帮助。如果您放下所有规则,则可能变得太宽泛而无法在此处解决。

答案 3 :(得分:0)

如果使用“ elif”,则会使计算机工作变得容易一些,因为它会首先检查“ if”,如果为true,它将忽略与该“ if”相关的所有“ elif”和“ else”,但是如果您在每种情况下都使用“ if”(就像您一样),则计算机将遍历每个“ if”语句并进行检查。我希望这是有道理的。