如何组织类的结构?

How to organize the structure of classes?

我正在为外汇市场(二元期权)交易编写一个顾问程序。使用福汇 API。对于那些有趣的人。我有 5 个货币对。每一个都包含五个不同时间范围内的报价历史。例如,假设从一分钟到五分钟。每个历史必须有三个变量。 (最大,最小,最后) 报价历史在等于一分钟的时间范围内从 FXCM 加载一次,然后针对所有其他时间范围进行计算。我还有一个方法(或者我可以将它们组合成一个方法)用于实际数据,分别每分钟、每两分钟等执行一次,以在相应的历史记录中记录新形成的蜡烛。 我将附上一个我看到但不喜欢的 class 结构。

class Pair:    
    def __init__(self, name):
        self.name = name

class Periods:     
    def __init__(self, name):
        self.name  = name
        self.one   = pd.DataFrame()
        self.two   = pd.DataFrame()
        self.three = pd.DataFrame()
        self.four  = pd.DataFrame()
        self.five  = pd.DataFrame()

    def get_historical_data(self): # Executed once
        self.one   = historical_data_one_minute
        self.two   = historical_data_two_minute
        self.three = historical_data_three_minute
        self.four  = historical_data_four_minute
        self.five  = historical_data_five_minute

    def set_actual_data(self, period): #Executed ones per minute
        if period == '1min':
            one_minute_candle = calculated_one_minute_candle
            self.one   = self.one.append(one_minute_candle)
        if period == '2min':
            two_minute_candle = calculated_two_minute_candle
            self.two   = self.two.append(two_minute_candle)
        ...

        if period == '5min':
            five_minute_candle = calculated_five_minute_candle
            self.five   = self.five.append(five_minute_candle)

如您所见,没有最大、最小和最后一个变量。这是因为我不知道如何把它们绑起来。我应该把 'Periods' 分成 class 吗,比如 One_minute、Two_minute 等等 添加变量还是有另一种方法?这个的 class 会不会太多了?

class One_minute:
    def __init__(self):
        self.largest = 0
        self.smallest = 0
        self.last = 0

    def get_historical_data(self):
        self.history = historical_data_one_minute
        self.largest = calculated_largest_from_historical_data_one_minute
        self.smallest = calculated_smallest_from_historical_data_one_minute
        self.last = calculated_last_from_historical_data_one_minute

总的来说,结构如下

(currency pair) - one_minute_history ---- largest
                |                    |___ smallest
                |                    |___ last
                |_two_minute_history ---- largest
                |                    |___ smallest
                |                    |___ last
                |_and so on

或者

(currency pair) ------ one_minute_history
                 |  |_ largest
                 |  |_ smallest
                 |  |_ last
                 |____ two_minute_history
                 |  |_ largest
                 |  |_ smallest
                 |  |_ last
                 |____ three_minute_history
                  ...

如果这样访问就方便了

eurusd.history[1] #gets one minute history
eurusd.history[1].largest or eurusd.largest.history[1]  #gets largest price of one minute history

或者可能更好。

总的来说,我将有 25 个不同的历史数据框,每个货币对 5 个。而且对于每个历史数据框,我将有三个变量

我希望我能解释一下我需要得到什么。提前致谢!

编辑: 我认为无论历史数据如何计算但回答你的问题 - 这是这个方法

    def get_historical_data(self, con): # Once
        dtn     = datetime.now()  
        hours   = dtn.hour + 3
        minutes = dtn.minute
    
        data = con.get_candles(instrument, period = 'm1', start=dtn - timedelta(hours=hours, minutes=minutes), end=dtn)        
        self.one['open']      = (data['bidopen']  + data['askopen'])  / 2
        self.one['high']      = (data['bidhigh']  + data['askhigh'])  / 2
        self.one['low']       = (data['bidlow']   + data['asklow'])   / 2
        self.one['close']     = (data['bidclose'] + data['askclose']) / 2
        self.one['direction'] = 'flat'
        self.one.loc[self.one['close'] - self.one['open'] >=  0.00002, "direction"] = "up"
        self.one.loc[self.one['close'] - self.one['open'] <= -0.00002, "direction"] = "down"
    
        s = (self.one['direction'] != self.one['direction'].shift()).cumsum()
        
        self.one['series'] = self.one.groupby(s).cumcount() + 1
        self.one.loc[self.one['direction'] == 'flat', 'series'] = self.one['series'].subtract(1)
        self.one = self.one.tz_localize(pytz.timezone('UTC'))
        self.one = self.one.tz_convert(pytz.timezone('Europe/Moscow'))    
        self.one.to_csv('history.csv', index=True)          
    
        dct = {'date': 'first', 'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last'}
        
        self.two   = self.one.reset_index().groupby(np.arange(len(self.one)) // 2).agg(dct).set_index('date')
        self.three = self.one.reset_index().groupby(np.arange(len(self.one)) // 3).agg(dct).set_index('date')
        self.four  = self.one.reset_index().groupby(np.arange(len(self.one)) // 4).agg(dct).set_index('date')
        self.five  = self.one.reset_index().groupby(np.arange(len(self.one)) // 5).agg(dct).set_index('date')

循环调用该函数。

con = fxcmpy.fxcmpy(config_file = 'fxcm.cfg') # Connection
periods = Periods("EUR/USD")
cycle_just_launched = True
while True:
    time.sleep(60)
    if cycle_just_launched:
        periods.get_historical_data(con)
    else:
        periods.set_actual_data(con, "1min")
    cycle_just_launched = False

似乎您需要封装“single-period 历史”的概念,然后您可以在此基础上构建其余部分。类似于:

class PeriodHistory:
    def __init__(self, name, period):
        self.name = name
        self.period = period # e.g. 1min, 2min, etc.
        self.data = pd.DataFrame()
        self.largest = 0
        self.smallest = 0
        self.latest = 0

    def load(self, historic_data):
        # initialize data, largest, smallest, latest from historical

    def update(self, new_data):
        # update variables based on new data and self.period

然后 class 将 multi-period 个历史合并为一个:

class MultiPeriodHistory:
    def __init__(self, name):
        self.name = name
        self.period = {}
        for i in range(1, 6):
            self.period[i] = PeriodHistory(self.name, i)
            self.period[i].load(history_data_for_period[i])

    def update(self):
        new_data = get_data_from_api(self.name)
        for i in range(1, 6):
            self.period[i].update(new_data)

然后您可以使用字典为每个货币对存储 multi-history:

currencies = ('eur', 'usd', 'jpy', 'gbp', 'chf')
history = {}
for c1 in currencies:
    for c2 in currencies:
        if c1 != c2:
            history[c1 + c2] = MultiPeriodHistory(c1 + c2)

现在,例如history['eurgbp'].period[3].smallest给你想要的。

您可能需要修改您的数据获取并稍微更新以适应这种模式,我 hand-waved 很多,因为我没有完整的图片。