Это долгое чтение, но я просмотрел множество примеров StackOverflow по созданию функций для итерации по фреймам данных и т. Д. И просто не смог найти ничего, что соответствовало бы моим потребностям. Я также использую Python и кодирование в целом только около 2 месяцев, поэтому я прошу прощения, если что-то неясно.
У меня есть фрейм данных с дневной ценовой историей, и я пытаюсь создать бэк-тест для сигналов покупки на основе этой стратегии:
Сначала мы ищем день, когда цена закрытия превышает цену закрытия как днем ранее, так и днем позже . Давайте назовем это «базовым днем».
Чтобы инициировать наш сигнал на покупку, мы ждем день, когда цена закрытия вернется выше «базового дня». Теперь у нас есть открытая позиция.
Мы удерживаем эту позицию до тех пор, пока не получим сигнал на продажу, противоположный тому, что искал наш сигнал на покупку. (т.е. цена закрытия ниже предыдущего дня, когда днем ранее и днем позже были выше)
Я хочу, чтобы за один раз была активна только одна покупка, пока мы не получим сигнал на продажу, и тогда процесс не начнется заново.
Ниже приведен пример кадра данных с небольшой частью данных, на которые я смотрю
import pandas as pd
data = {
'date': [1/3/2000,1/4/2000,1/5/2000,1/6/2000,1/7/2000,1/10/2000,1/11/2000,1/12/2000,1/13/2000,1/14/2000,1/18/2000,1/19/2000,1/20/2000,1/21/2000,1/24/2000,1/25/2000,1/26/2000,1/27/2000,1/28/2000,1/31/2000,2/1/2000,2/2/2000,2/3/2000,2/4/2000,2/7/2000,2/8/2000,2/9/2000,2/10/2000,2/11/2000,2/14/2000,2/15/2000,2/16/2000,2/17/2000,2/18/2000,2/22/2000,2/23/2000,2/24/2000,2/25/2000,2/28/2000,2/29/2000],
'close': [308.3,315.3,314.4,307.5,309.8,313.4,310.7,324.2,332.5,348.8,351.1,348.2,348.7,343.5,343,343.3,342.4,343,334.4,334.6,336,333.8,331.6,332.8,335.9,341.2,338.4,342.1,343.2,339.5,346.9,342,339.6,337.4,335,330.8,331.3,331.1,332.6,335.1]}
df = pd.DataFrame(data)
## Create columns to compare price to day before and day after
df['prev_close'] = df['close'].shift(1)
df['next_close'] = df['close'].shift(-1)
## BOOLEAN TO RETURN IF PRICE IS LOWER THAN PREVIOUS AND NEXT DAY
df['high_high'] = ((df['prev_close']) > df['close']) & ((df['next_close']) > df['close'])
## BOOLEAN TO RETURN TRUE IF PRICE IS GREATER THAN PREVIOUS AND NEXT DAY
df['low_low'] = ((df['prev_close']) < df['close']) & ((df['next_close']) < df['close'])
## RETURN PRICE OF MOST RECENT true IN low_low
df['comp_price'] = df['close'].where(df['low_low'] == True)
## FILL IN BLANKS WITH PREVIOUS VALUE TO KEEP COMPARISON PRICE ACTIVE
df['comp_price'].fillna(method='pad',inplace=True)
## CREATE SELL COMPARISON DATE TO REFERENCE WHEN CLOSING POSITION
df['sell_comp'] = df['close'].where(df['high_high'] == True)
df['sell_comp'].fillna(method='pad',inplace=True)
## CREATE BUY SIGNAL
df['buy_sig'] = df['close'] > df['comp_price']
## DESIGNATE FIRST INSTANCE OF BUY SIGNAL AS DAY TO OPEN POSITION
df['open_pos'] = (df['buy_sig'] == 1) & (df['buy_sig'].shift(1) != 1)
df['take_signal'] = (df['buy_sig'] == 1) & (df['open_pos'] == True)
df['open_pos_price'] = df['close'].where(df['take_signal'] == True)
df['open_pos_price'].fillna(method='pad',inplace=True)
## CREATE SELL SIGNAL
df['sell_sig'] = df['close'] < df['sell_comp']
## DESIGNATE FIRST INSTANCE OF SELL AS DAY TO CLOSE POSITION
df['close_pos'] = (df['sell_sig'] == True) & (df['sell_sig'].shift(1) == False)
## CREATE COLUMNS THAT ORGANIZE WHEN POSITION WAS OPENED
df['open_pos_date'] = df['date'].where((df['open_pos'] == True)&(df['take_signal'] == True))
df['open_pos_date'].fillna(method='pad',inplace=True)
## CREATE COLUMNS SHOW DATE AND PRICE OF CLOSING POSITION
df['close_pos_price'] = df['close'].where(df['close_pos'] == True)
df['close_pos_date'] = df['date'].where((df['close_pos'] == True))
## CALCULATE GAIN FOR TRADE
df['gain'] = (df['close_pos_price'] - df['open_pos_price']).where((df['close_pos_price'] > 0)& (df['open_pos_price'] > 0))
Затем я создал еще один фрейм данных, который отображал результаты при получении сигналов на продажу, чтобы впоследствии я мог превратить результаты в кортежи и выполнить итерацию, чтобы добавить стоимость транзакции и т. Д., Чтобы закончить для целей построения графиков.
strat_df = df.loc[(df['close_pos'] == True)&(df['sell_sig'] == True), ['open_pos_date','open_pos_price', 'close_pos_date','close_pos_price','gain']]
Я вижу несколько экземпляров одного и того же open_pos_date
с разными значениями close_pos_date
. Где-то по пути я разрешаю работать нескольким открытым позициям.
Я хочу оставить свой первый сигнал на покупку в качестве единственной позиции, игнорируя все остальные сигналы на покупку, пока не получу сигнал на продажу. В этот момент я хочу найти новый сигнал на покупку и удерживать эту позицию только до тех пор, пока не получу новую продажу.
Вероятно, я создал больше столбцов, чем необходимо, но мне было трудно найти способ получить уникальный сигнал для открытия позиции, а затем сравнить цену с той, какой будет эта цена, когда я получу сигнал на продажу. Если кто-то может порекомендовать более чистый способ сделать это, я бы с радостью отказался от своей первой попытки и попробовал.