I am programming an advisor for trading in the foreign exchange market (binary options). Using FXCM API. For those who interesting. And I have a 5 currency pairs. Each of which contains the history of quotes in five different time frames. For example, let's say from one minute to five minutes. Each history must have three variables. (largest, smallest, last) The history of quotes is loaded from FXCM once in a time frame equal to one minute and then calculated for all other time frames. Also I have a methods (or maybe I can combine them into one method) for actual data which are executed once a minute, every two minutes, and so on, respectively, to record a newly formed candle in the corresponding history. I will attach a class structure that I see, but which I do not like.
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)
As you noticed there is no largest, smallest and last variables. It's because I don't know how to tie them up. Should I to break 'Periods' into classes like One_minute, Two_minute and so on to add variables or there is another way? Will there be too many classes for this?
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
In general, the structure is as follows
(currency pair) - one_minute_history ---- largest
| |___ smallest
| |___ last
|_two_minute_history ---- largest
| |___ smallest
| |___ last
|_and so on
Or
(currency pair) ------ one_minute_history
| |_ largest
| |_ smallest
| |_ last
|____ two_minute_history
| |_ largest
| |_ smallest
| |_ last
|____ three_minute_history
...
It would be convenient if access was carried out like this
eurusd.history[1] #gets one minute history
eurusd.history[1].largest or eurusd.largest.history[1] #gets largest price of one minute history
Or it could be something better.
In total, it turns out that I will have 25 different history data frames, 5 for each currency pair. And also for each history data frame, I will have three variables
I hope I could explain what I need to get. Thank you in advance!
Edit: I think it's no matter how historical data calculated but responding on your question - here is this method
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')
The function is called in a loop.
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
Seems like you need to encapsulate the concept of a "single-period history" and then you can build the rest on top of that. Something like:
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
Then a class to combine multi-period histories into one:
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)
And then you can use a dict to store multi-history for each currency pair:
currencies = ('eur', 'usd', 'jpy', 'gbp', 'chf')
history = {}
for c1 in currencies:
for c2 in currencies:
if c1 != c2:
history[c1 + c2] = MultiPeriodHistory(c1 + c2)
Now e.g. history['eurgbp'].period[3].smallest
will give you what you want.
You may need to modify your data fetch and update a bit to fit this pattern, I hand-waved a lot since I don't have the full picture.