Spaces:
Sleeping
Sleeping
Delete app.py
Browse files
app.py
DELETED
|
@@ -1,117 +0,0 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
-
import yfinance as yf
|
| 3 |
-
import pandas as pd
|
| 4 |
-
import numpy as np
|
| 5 |
-
|
| 6 |
-
def ema(s, n):
|
| 7 |
-
return s.ewm(span=int(n), adjust=False).mean()
|
| 8 |
-
|
| 9 |
-
def rsi(s, n=9):
|
| 10 |
-
d=s.diff()
|
| 11 |
-
up=d.clip(lower=0).ewm(alpha=1/n, adjust=False).mean()
|
| 12 |
-
dn=(-d.clip(upper=0)).ewm(alpha=1/n, adjust=False).mean()
|
| 13 |
-
rs=up/dn.replace(0,np.nan)
|
| 14 |
-
return 100-100/(1+rs)
|
| 15 |
-
|
| 16 |
-
def load_data(ticker, period, interval):
|
| 17 |
-
df=yf.download(ticker,period=period,interval=interval,auto_adjust=False,progress=False,threads=False)
|
| 18 |
-
if df is None or df.empty: return None
|
| 19 |
-
if isinstance(df.columns,pd.MultiIndex): df.columns=df.columns.get_level_values(0)
|
| 20 |
-
df.columns=[str(c).title() for c in df.columns]
|
| 21 |
-
needed=["Open","High","Low","Close"]
|
| 22 |
-
if not set(needed).issubset(df.columns): return None
|
| 23 |
-
return df.dropna(subset=needed).copy()
|
| 24 |
-
|
| 25 |
-
def build_signals(df, fast, slow, sig, rsi_len, fee_pct, slippage_pct):
|
| 26 |
-
c=df["Close"]
|
| 27 |
-
macd=ema(c,fast)-ema(c,slow)
|
| 28 |
-
macd_sig=ema(macd,sig)
|
| 29 |
-
rs=rsi(c,rsi_len)
|
| 30 |
-
e5,e9=ema(c,5),ema(c,9)
|
| 31 |
-
buy=(macd>macd_sig)&(rs>50)&(e5>e9)
|
| 32 |
-
sell=(macd<macd_sig)&(rs<50)&(e5<e9)
|
| 33 |
-
# Avoid look-ahead: signal on close, enter at next bar open.
|
| 34 |
-
raw=np.select([buy,sell],[1,-1],default=0)
|
| 35 |
-
pos=pd.Series(raw,index=df.index).shift(1).fillna(0)
|
| 36 |
-
# Position changes close previous position and open new one at current open.
|
| 37 |
-
open_px=df["Open"].astype(float)
|
| 38 |
-
close_px=c.astype(float)
|
| 39 |
-
ret=close_px.pct_change().fillna(0)
|
| 40 |
-
# Approximate bar return while holding prior signal; fee/slippage charged on position changes.
|
| 41 |
-
strat=pos*ret
|
| 42 |
-
changes=pos.diff().abs().fillna(pos.abs())
|
| 43 |
-
costs=changes*(float(fee_pct)+float(slippage_pct))/100
|
| 44 |
-
net=strat-costs
|
| 45 |
-
equity=(1+net).cumprod()
|
| 46 |
-
return pos, net, equity, macd, macd_sig, rs, changes
|
| 47 |
-
|
| 48 |
-
def backtest(ticker, interval, period, initial, fast, slow, sig, rsi_len, fee, slip):
|
| 49 |
-
try:
|
| 50 |
-
df=load_data(ticker.strip(),period,interval)
|
| 51 |
-
if df is None or len(df)<max(int(slow),int(rsi_len))+10:
|
| 52 |
-
return "Veri alınamadı veya yeterli mum yok. Sembol ve periyodu kontrol edin.",None
|
| 53 |
-
pos, net, equity, macd, ms, rs, changes=build_signals(df,int(fast),int(slow),int(sig),int(rsi_len),float(fee),float(slip))
|
| 54 |
-
# Trades are contiguous non-flat position runs. Approximate trade stats from bar returns.
|
| 55 |
-
active=pos.ne(0)
|
| 56 |
-
starts=active & ~active.shift(1,fill_value=False)
|
| 57 |
-
ends=active & ~active.shift(-1,fill_value=False)
|
| 58 |
-
trade_returns=[]
|
| 59 |
-
for start_idx in np.flatnonzero(starts.to_numpy()):
|
| 60 |
-
end_candidates=np.flatnonzero(ends.to_numpy()[start_idx:])
|
| 61 |
-
if len(end_candidates)==0: continue
|
| 62 |
-
end_idx=start_idx+end_candidates[0]
|
| 63 |
-
trade_returns.append(float((1+net.iloc[start_idx:end_idx+1]).prod()-1))
|
| 64 |
-
trades=np.array(trade_returns,dtype=float)
|
| 65 |
-
wins=int((trades>0).sum())
|
| 66 |
-
win_rate=100*wins/len(trades) if len(trades) else 0
|
| 67 |
-
total_return=float(equity.iloc[-1]-1)
|
| 68 |
-
peak=equity.cummax()
|
| 69 |
-
dd=equity/peak-1
|
| 70 |
-
max_dd=float(dd.min())
|
| 71 |
-
gross_profit=float(trades[trades>0].sum()) if len(trades) else 0
|
| 72 |
-
gross_loss=float(-trades[trades<0].sum()) if len(trades) else 0
|
| 73 |
-
pf=gross_profit/gross_loss if gross_loss>0 else (float("inf") if gross_profit>0 else 0)
|
| 74 |
-
final=float(initial)*(1+total_return)
|
| 75 |
-
report=(f"## {ticker} — Backtest sonuçları\\n"
|
| 76 |
-
f"- **İşlem sayısı:** {len(trades)}\\n"
|
| 77 |
-
f"- **Kazanma oranı:** {win_rate:.2f}%\\n"
|
| 78 |
-
f"- **Net getiri:** {total_return*100:.2f}%\\n"
|
| 79 |
-
f"- **Başlangıç bakiyesi:** {float(initial):,.2f}\\n"
|
| 80 |
-
f"- **Teorik bitiş bakiyesi:** {final:,.2f}\\n"
|
| 81 |
-
f"- **Maksimum düşüş (equity):** {max_dd*100:.2f}%\\n"
|
| 82 |
-
f"- **Profit factor (işlem getirilerinden yaklaşık):** {pf:.2f}\\n\\n"
|
| 83 |
-
f"**Not:** Bu, MACD/RSI/EMA örnek stratejisinin yaklaşık backtestidir; MT4 EA'nın birebir portu değildir. "
|
| 84 |
-
f"Yahoo Finance verileri, spread/komisyon ve kayma varsayımları sonuçları etkiler. "
|
| 85 |
-
f"Pozisyonlar kapanıştan sonraki mumda açılacak şekilde geciktirilmiştir; emir icrası ve lot artırma EA mantığı modellenmemiştir.")
|
| 86 |
-
out=df.copy()
|
| 87 |
-
out["MACD"]=macd; out["MACD_signal"]=ms; out[f"RSI_{int(rsi_len)}"]=rs
|
| 88 |
-
out["Position"]=pos.map({1:"LONG",-1:"SHORT",0:"FLAT"})
|
| 89 |
-
out["Strategy_return_%"]=net*100
|
| 90 |
-
out["Equity"]=float(initial)*equity
|
| 91 |
-
out["Drawdown_%"]=dd*100
|
| 92 |
-
out=out.reset_index().tail(500)
|
| 93 |
-
return report,out
|
| 94 |
-
except Exception as e:
|
| 95 |
-
return f"Backtest hatası: {e}",None
|
| 96 |
-
|
| 97 |
-
with gr.Blocks(title="AF Global Backtest Terminal",theme=gr.themes.Soft()) as demo:
|
| 98 |
-
gr.Markdown("# AF Global Expert — YFinance Backtest")
|
| 99 |
-
gr.Markdown("E-posta gönderimi yoktur. Veriler Yahoo Finance'tan çekilir. Strateji, örnek MACD/RSI/EMA birleşimidir; orijinal EA'nın birebir dönüşümü değildir.")
|
| 100 |
-
with gr.Row():
|
| 101 |
-
ticker=gr.Textbox(label="Yahoo sembolü",value="EURUSD=X")
|
| 102 |
-
interval=gr.Dropdown(["5m","15m","30m","60m","1h","1d","1wk"],value="1h",label="Zaman dilimi")
|
| 103 |
-
period=gr.Dropdown(["5d","1mo","3mo","6mo","1y","2y","5y"],value="1y",label="Geçmiş")
|
| 104 |
-
with gr.Row():
|
| 105 |
-
initial=gr.Number(label="Başlangıç bakiyesi",value=10000)
|
| 106 |
-
fee=gr.Number(label="Komisyon (%) / pozisyon değişimi",value=0.02)
|
| 107 |
-
slip=gr.Number(label="Kayma (%) / pozisyon değişimi",value=0.01)
|
| 108 |
-
with gr.Row():
|
| 109 |
-
fast=gr.Number(label="MACD fast",value=8,precision=0)
|
| 110 |
-
slow=gr.Number(label="MACD slow",value=17,precision=0)
|
| 111 |
-
sig=gr.Number(label="MACD signal",value=9,precision=0)
|
| 112 |
-
rsi_len=gr.Number(label="RSI period",value=9,precision=0)
|
| 113 |
-
btn=gr.Button("Veriyi çek ve backtest yap",variant="primary")
|
| 114 |
-
report=gr.Markdown()
|
| 115 |
-
table=gr.Dataframe(label="Son 500 mum — sinyal, getiri ve equity",interactive=False)
|
| 116 |
-
btn.click(backtest,[ticker,interval,period,initial,fast,slow,sig,rsi_len,fee,slip],[report,table])
|
| 117 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|