Pandas serileri üzerinde max kullanımında hata alıyorum

Merhaba arkadaşlar,
Borsadan OHLCV verileri çekiyorum. Bu verilere göre alım satım sinyali oluşturmaya çalışıyorum. Alım satım fonksiyonunda max fonksiyonu ile iki verinin en max ini almaya çalışıyorum fakat olmuyor. max(dataframe[‘high’].shift(-3),dataframe[‘high’].shift(-2)) sıkıntı burda buranın farklı bir alternatifi varmı. Neden hata alıyorum onuda bilmiyorum açıkcası.

def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
			(dataframe['cci_one'] < -189)&
            (dataframe['high'].shift(-1) <  max(dataframe['high'].shift(-3),dataframe['high'].shift(-2)))
			),
             'buy'] = 1
		return dataframe

HATA ÇIKTISI:

strategy.interface - WARNING - Unable to analyze candle (OHLCV) data for pair XTM/USDT: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
strategy.strategy_wrapper - WARNING - Strategy caused the following exception: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().<bound method IStrategy._analyze_ticker_internal of <stra1.stra1 object at 0x7f9b963c1280>>

Merhaba, küçük bir dataframe örneği üzerinden istediğiniz çıktıyı belirtebilir misiniz?

Mesela

Eldeki dataframe:

     A    B
0  0.0  0.0
1  1.0  1.0
2  2.0  0.0
3  3.0  1.0
4  4.0  0.0

İstenen: B sütunundaki değer 1 ise A sütununda ona karşılık gelen değerin 2 katına çıkarılması:

     A    B
0  0.0  0.0
1  2.0  1.0
2  2.0  0.0
3  6.0  1.0
4  4.0  0.0

Denenen:

...

hocam merhaba, hızlı cevabınız için içtenlikle teşekkürler.

Hocam çektiğim veriler OHLC verileri örnek api çıktısı için link şu şekilde.
https://api.kucoin.com/api/v1/market/candles?symbol=BTC-USDT&type=1hour&startAt=1562460061

Verilerin açılımıda şu şekilde.

[
    [
        "1545904980",             //Start time of the candle cycle
        "0.058",                  //opening price
        "0.049",                  //closing price
        "0.058",                  //highest price  ben burayı çekiyorum kendi kodumda bura ile karşılaştırıyorum
        "0.049",                  //lowest price
        "0.018",                  //Transaction volume
        "0.000945"                //Transaction amount
    ],
    [
        "1545904920",
        "0.058",
        "0.072",
        "0.072",
        "0.058",
        "0.103",
        "0.006986"
    ]
]

Veri tiplerindemi oluyor, normal şartlar altında max komutu büyük olanı vermesi gerekmiyormu.

Tamamdır, mesela ilk 10 satırınız şöyleyse

      open    close     high      low         vol        amount
0  48531.1  48491.9  48698.5  48253.2  418.730091  2.028705e+07
1  49014.4  48531.0  49019.7  48504.4  400.754405  1.951507e+07
2  48694.7  49014.4  49255.0  48386.0  485.181986  2.363863e+07
3  49208.4  48701.4  49218.6  48626.5  367.919957  1.800141e+07
4  49144.9  49208.5  49435.1  48869.1  304.266157  1.495215e+07
5  48958.9  49144.9  49229.0  48918.3  187.817402  9.221754e+06
6  48777.7  48958.9  48979.0  48727.0  133.223491  6.508688e+06
7  48721.3  48777.7  48934.0  48618.7  181.006848  8.828849e+06
8  48888.1  48721.2  49027.8  48695.0  230.364232  1.126743e+07
9  48513.5  48888.1  48903.7  48502.6  196.925498  9.595000e+06

sizin elde etmek istediğiniz çıktı nasıldır onu aktarabilir misiniz bunun üzerinden? Koddan veya yazıdan tam anlayamadım maalesef…

Hocam ben sorunlu kodu (dataframe[‘high’].shift(-1) < max(1,2)) bu şekilde bile yapsam bana hatayı döndürüyor. High sutununda herhangi bir satırdaki iki satırı karşılaştırmam gerekiyor. Veriler geliyor sıkıntı yok, sadece büyük olanı oraya yazdırmak amaçım.

Mesala bakın
(dataframe[‘low’].shift(-1)<dataframe[‘low’].shift(-2))&
(dataframe[‘low’].shift(-1)<dataframe[‘low’].shift(-3))

Bu kodlar şartları yerine getiriyor çalışıyor fakat aşağıdaki kod çalışmıyor

(dataframe['high'].shift(-1) <  max(dataframe['high'].shift(-3),dataframe['high'].shift(-2)))

burada max yerine başka birşey deneyebilirmiyim büyük olanı oraya yazdıracak ve şartı yerine getirecek.Bir çıktı almak değil amaçım sinyal üretmeye çalışıyorum hocam. Gelen rakamlar arasında büyük olanı oraya yazdırıp sinyal üretmek. Pandas bilmiyorum, sorunuza düzgün cevap vermemiş olabilirim kusura bakmayın bilmediğimden oda.

max(dataframe['high'].shift(-3), dataframe['high'].shift(-2))

dediğinizde max fonksiyonuna iki pandas serisi gönderiyorsunuz. s1 ve s2 diyelim yazması daha kolay olsun:

max(s1, s2)

max'ın aşağı yukarı yaptığı şey kendisine verilen argümanları < ile karşılaştırarak “en büyüğünü” bulmaktır. Yani ilk s1 < s2'yi değerlendiriyor. Bakıyoruz ne döndürdüğüne bunun:

>>> # öylesine 2 seri
>>> s1 = pd.Series([12, 3, -5])
>>> s2 = pd.Series([0, 9, 87])

>>> s1 < s2
0    False
1     True
2     True
dtype: bool

s1 < s2 başka bir seri döndürdü (elemanları bu iki serinin eleman-eleman karşılaştırmasının sonucu oluşan). max şimdi ne yapıyor? Bunu “boolean” bağlamında değerlendirmek istiyor. Niye? “Bu bundan daha küçük mü” evet/hayır sorusuna True/False bir cevap bulsun ki karşılaştırmayı sürdürüp en büyüğü bulsun. Örneğin max(4, 12)'ye bakıyor olsaydık, 4 < 12'nün boolean bağlamında True vermesinden ötürü max yanıtın 12 olduğunu söyleyebilir.

Ama s1 < s2 direkt True veya False döndürmedi, bool'un içine paslayıp True veya False'a indirgenmesini bekleyelim (mesela if'in devamına yazılan ifadeler dolaylı yoldan bool'a tabi tutulur):

>>> bool(s1 < s2)
ValueError: The truth value of a Series is ambiguous.
Use a.empty, a.bool(), a.item(), a.any() or a.all().

?! Sizin aldığınız hatayı alıyoruz… Bir serinin doğruluk değerini belirlemekten kaçınıyor, düz Python’daki gibi liste doluysa True'ya, değilse False'a dönme gibi bir durum olmuyor. Böyle yapmasının makul olabileceğine dair şu örnekleri verebiliriz:

# eleman var ama False; True mu döndürsün False mu?
bool(pd.Series([False]))
# elemanların biri True diğeri False; ne döndürsün? Kuantum beni aşar :p
bool(pd.Series([True, False]))

Peki bunun üstesinden nasıl geliriz? İki seri arası eleman-eleman karşılaştırma yapabilecek “vektörize” fonksiyonlar sayesinde. numpy kullanmaktan imtina etmiyorsanız bunlardan ilki np.maximum'dur:

>>> import numpy np
>>> np.maximum(s1, s2)
0    12
1     9
2    87
dtype: int64

pandas sınrılarında kalmak istiyorsanız s1 ve s2'yi bir dataframe’de toplayıp onun kendine has max metodunu kullabilirsiniz:

# "concatenate" ediyoruz; `axis=1` yan yana yapıştırmayı sağlıyor
>>> ikisi_beraber = pd.concat([s1, s2], axis=1)
>>> ikisi_beraber
    0   1
0  12   0
1   3   9
2  -5  87

# Buradaki `axis=1` ise satır yönünde maksimum almasını söylüyor
# Dolayısıyla satır sayısı uzunluğunda bir seri elde ediyoruz
>>> maksimumlari = ikisi_beraber.max(axis=1)
>>> maksimumlari
0    12
1     9
2    87
dtype: int64

İkisi de aynı sonucu veriyor, np.maximum daha kısa gibi duruyor. (Bu arada numpy kullanmakta bir sıkıntı görmeyeceğinizi düşünüyorum, en kötü ihtimalle pd.np'den yürüyebilirsiniz :ğ)

Bunları göz önüne alıp kodunuzun ilgili kısmını şöyle değiştirebiliriz:

# birden fazla erişiyoruz, okunabilirliği de artırabilir kodu kısaltmasına ek
high = dataframe.high

...
      (high.shift(-1) < np.maximum(high.shift(-3), high.shift(-2)))
...

Son olarak, shift(-1) (ve -2, -3) kullanarak gelecekteki verilere erişiyorsunuz ama yaptığınız işten anlamıyorum o yüzden görmezden gelebilirsiniz bu eklemeyi :d


Kuantum pandas’ı aşıyor olabilir ama her yerde öyle olmak zorunda değil :d

Teşekkürler hocam, denedim np.maximum işe yarıyor gözüküyor şuan için. Ne kadar çok şey yazmışsınız çok teşekkür ederim. Dediklerinizi derinlemesine düşüneceğim.