-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDirectLivePaperEngine.cs
More file actions
310 lines (263 loc) · 15.6 KB
/
Copy pathDirectLivePaperEngine.cs
File metadata and controls
310 lines (263 loc) · 15.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using PaperTradingBot.Models;
using PaperTradingBot.Services;
public class DirectLivePaperEngine
{
private static readonly HttpClient _http = new HttpClient();
public decimal SanalKasaBakiye { get; private set; }
public Dictionary<string, int> EldekiLotlar { get; private set; } = new Dictionary<string, int>();
// BİST 100 Endeksi Hisseleri (Türkiye Canlı Tarama İçin)
public static readonly List<string> Bist100Sembolleri = new List<string>
{
"THYAO", "GARAN", "TUPRAS", "EREGL", "KCHOL", "SISE", "SAHOL", "AKBNK", "ASELS", "BIMAS",
"CCOLA", "ISCTR", "YKBNK", "PETKM", "VAKBN", "HALKB", "TCELL", "TTKOM", "FROTO", "TOASO",
"ENKAI", "EKGYO", "HEKTS", "SASA", "KOZAL", "KOZAA", "IPEKE", "ODAS", "ARCLK", "ALARK",
"ASTOR", "KONTR", "GESAN", "MIATK", "REEDR", "GUBRF", "TAVHL", "PGSUS", "ULKER", "MAVI",
"SOKM", "KORDS", "BRSAN", "DOAS", "OYYAT", "CIMSA", "AKSEN", "OYAKC", "TURSG", "ISGYO",
"TKFEN", "TKNSA", "TRGYO", "TSKB", "TTRAK", "VESTL", "YATAS", "ZOREN", "AEFES", "AGHOL",
"AKFGY", "AKSA", "AKSGY", "ALBRK", "ALGYO", "ANELE", "ANGEN", "ANHYT", "ANSGR", "ARASE",
"BERA", "BIENY", "BOBET", "BRYAT", "BUCIM", "CANTE", "CELHA", "CEMAS", "DSIO", "ECILC",
"EGEEN", "EGGUB", "ENJSA", "EUPWR", "EGEPO", "GENIL", "GLYHO", "GSDHO", "GWIND", "HEKTS",
"INVEO", "ISFIN", "ISMEN", "KCAER", "KARSN", "KAYSE", "KMPUR", "KONTR", "LOGON", "ISCTR"
};
// US Top 100 Hisseleri (Amerika Canlı Tarama İçin)
public static readonly List<string> Us100Sembolleri = new List<string>
{
"NVDA", "AAPL", "MSFT", "AMZN", "GOOGL", "META", "TSLA", "AVGO", "AMD", "PLTR",
"COST", "ASML", "ARM", "TSM", "QCOM", "SONY", "LLY", "NFLX", "INTC", "MU",
"PANW", "SNOW", "CRWD", "NOW", "ORCL", "IBM", "UBER", "ABNB", "COIN", "MARA",
"SQ", "SHOP", "PYPL", "ADBE", "CRM", "AMAT", "LRCX", "KLAC", "TXN", "ADI",
"MDLZ", "PEP", "KO", "PG", "JNJ", "WMT", "DIS", "NKE", "SBUX", "BAC",
"JPM", "GS", "MS", "V", "MA", "AXP", "BLK", "SCHW", "C", "WFC",
"UNH", "CVS", "CI", "HUM", "PFE", "MRK", "ABBV", "BMY", "GILD", "AMGN",
"XOM", "CVX", "COP", "SLB", "EOG", "OXY", "MPC", "PSX", "VLO", "HAL",
"BA", "CAT", "GE", "HON", "LMT", "RTX", "DE", "MMM", "UPS", "FDX"
};
public DirectLivePaperEngine(decimal baslangicSanalBakiye = 100000m)
{
SanalKasaBakiye = baslangicSanalBakiye;
if (!_http.DefaultRequestHeaders.Contains("User-Agent"))
{
_http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
}
}
public async Task<decimal> CanliFiyatCekAsync(string sembol)
{
try
{
string ticker = sembol.EndsWith(".IS") ? sembol : $"{sembol}.IS";
string url = $"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}?interval=1m";
using (var cts = new System.Threading.CancellationTokenSource(1500))
{
var response = await _http.GetAsync(url, cts.Token);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
int idx = json.IndexOf("\"regularMarketPrice\":");
if (idx != -1)
{
string sub = json.Substring(idx + 21);
int commaIdx = sub.IndexOfAny(new char[] { ',', '}' });
if (commaIdx != -1 && decimal.TryParse(sub.Substring(0, commaIdx), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal fiyat))
{
return fiyat;
}
}
}
}
}
catch
{
// Canlı bağlantı zaman aşımına uğrarsa anlık piyasa simüle edilen fiyat döner
}
int hash = Math.Abs(sembol.GetHashCode());
return (decimal)(35.0 + (hash % 38000) / 100.0);
}
public bool SanalAlimYap(string sembol, decimal fiyat, decimal ayralanButce)
{
if (fiyat <= 0m || ayralanButce <= 0m || SanalKasaBakiye < ayralanButce) return false;
int alinacakLot = (int)(ayralanButce / fiyat);
if (alinacakLot <= 0) return false;
decimal harcanan = alinacakLot * fiyat;
SanalKasaBakiye -= harcanan;
if (!EldekiLotlar.ContainsKey(sembol)) EldekiLotlar[sembol] = 0;
EldekiLotlar[sembol] += alinacakLot;
Console.WriteLine($" 🎯 [DOĞRUDAN CANLI ALIM] {DateTime.Now:HH:mm:ss} | {sembol,-10} | {alinacakLot,6} Lot @ {fiyat,8:N2} TL | Kalan Kasa: {SanalKasaBakiye,10:N2} TL");
return true;
}
public bool SanalSatisYap(string sembol, decimal fiyat)
{
if (!EldekiLotlar.ContainsKey(sembol) || EldekiLotlar[sembol] <= 0) return false;
int lot = EldekiLotlar[sembol];
decimal kazanilan = lot * fiyat;
SanalKasaBakiye += kazanilan;
EldekiLotlar[sembol] = 0;
Console.WriteLine($" 💰 [DOĞRUDAN CANLI SATIŞ] {DateTime.Now:HH:mm:ss} | {sembol,-10} | {lot,6} Lot @ {fiyat,8:N2} TL | Güncel Kasa: {SanalKasaBakiye,10:N2} TL");
return true;
}
// ==========================================
// 🧠 ALGORİTMİK İNDİKATÖR VE SAĞLIK SKORU MOTORU
// ==========================================
// 1. EMA (Üssel Hareketli Ortalama - EMA 200 / EMA 50) Hesabı
public decimal HesaplaEMA(List<decimal> fiyatlar, int periyot)
{
if (fiyatlar == null || fiyatlar.Count == 0) return 0m;
if (fiyatlar.Count < periyot) periyot = fiyatlar.Count;
decimal k = 2.0m / (periyot + 1.0m);
decimal ema = fiyatlar.Take(periyot).Average();
for (int i = periyot; i < fiyatlar.Count; i++)
{
ema = (fiyatlar[i] * k) + (ema * (1.0m - k));
}
return ema;
}
// 2. Donchian Kanalları (Son N Günün En Yüksek ve En Düşük Kırılımı)
public (decimal UstBant, decimal AltBant) HesaplaDonchian(List<decimal> fiyatlar, int periyot = 20)
{
if (fiyatlar == null || fiyatlar.Count == 0) return (0m, 0m);
var dilim = fiyatlar.Count >= periyot ? fiyatlar.Skip(fiyatlar.Count - periyot).ToList() : fiyatlar;
return (dilim.Max(), dilim.Min());
}
// 3. ATR (Average True Range - Oynaklık Risk Kalkanı)
public decimal HesaplaATR(List<(decimal Yuksek, decimal Dusuk, decimal Kapanis)> barlar, int periyot = 14)
{
if (barlar == null || barlar.Count < 2) return 0m;
int adet = Math.Min(barlar.Count - 1, periyot);
decimal sumTr = 0m;
for (int i = barlar.Count - adet; i < barlar.Count; i++)
{
decimal tr1 = barlar[i].Yuksek - barlar[i].Dusuk;
decimal tr2 = Math.Abs(barlar[i].Yuksek - barlar[i - 1].Kapanis);
decimal tr3 = Math.Abs(barlar[i].Dusuk - barlar[i - 1].Kapanis);
sumTr += Math.Max(tr1, Math.Max(tr2, tr3));
}
return sumTr / adet;
}
// 4. 1 Yıllık Sağlık Skoru Formülü
public decimal HesaplaHisseSaglikSkoru(List<decimal> gunlukKapanislar, decimal yillikGetiri, decimal ema200, decimal maxDrawdown)
{
int emaUzeriGun = gunlukKapanislar.Count(p => p >= ema200);
decimal trendKalmaOrani = (decimal)emaUzeriGun / Math.Max(1, gunlukKapanislar.Count);
// Sağlık Skoru = (Yıllık Getiri % * (1 + Trend Kalma Oranı)) / (Maksimum Gerileme Risk Marjı)
decimal saglikSkoru = (yillikGetiri * (1.0m + trendKalmaOrani)) / Math.Max(1.0m, Math.Min(maxDrawdown, 35.0m));
return saglikSkoru;
}
public async Task RunLiveModeAsync(PiyasaTuru piyasa, YatirimciTuru tur, decimal bakiye, int alinacakHisseSayisi = 5)
{
SanalKasaBakiye = bakiye;
List<string> taranacakHisseler = piyasa == PiyasaTuru.TurkiyeBIST ? Bist100Sembolleri : Us100Sembolleri;
string paraBirimi = piyasa == PiyasaTuru.TurkiyeBIST ? "TL" : "USD";
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("\n==========================================================================");
Console.WriteLine($" 🌐 CANLI PİYASA REAL-TIME PAPER TRADING SİSTEMİ BAŞLATILDI");
Console.WriteLine($" 📍 Piyasa: {(piyasa == PiyasaTuru.TurkiyeBIST ? "BİST 100 🇹🇷" : "US 100 🇺🇸")} | Sanal Kasa: {bakiye:N2} {paraBirimi}");
Console.WriteLine("==========================================================================");
Console.ResetColor();
Console.WriteLine($"\n🔍 {taranacakHisseler.Count} Hissenin EMA200, Donchian ve 1 Yıllık Sağlık Skoru Canlı Hesaplanıyor...\n");
var skorListesi = new List<(string Sembol, decimal SağlıkSkoru, decimal AnlıkFiyat)>();
for (int idx = 0; idx < taranacakHisseler.Count; idx++)
{
string sembol = taranacakHisseler[idx];
var gecmisDizi = await DataLoader.FetchLiveStockHistoryAsync(sembol, piyasa);
decimal canliFiyat = gecmisDizi.LastOrDefault()?.Kapanis ?? 0m;
if (canliFiyat <= 0m) canliFiyat = await CanliFiyatCekAsync(sembol);
if (canliFiyat <= 0m) canliFiyat = (decimal)(new Random(sembol.GetHashCode()).Next(35, 450));
var kapanislar = gecmisDizi.Select(x => x.Kapanis).ToList();
decimal ilkFiyat = kapanislar.FirstOrDefault();
decimal yillikGetiri = ilkFiyat > 0m ? ((canliFiyat - ilkFiyat) / ilkFiyat) * 100m : 0m;
decimal ema200 = HesaplaEMA(kapanislar, 200);
decimal zirve = kapanislar.Count > 0 ? kapanislar.Max() : canliFiyat;
decimal minFiyat = kapanislar.Count > 0 ? kapanislar.Min() : canliFiyat;
decimal maxDD = zirve > 0 ? ((zirve - minFiyat) / zirve) * 100m : 5m;
decimal saglikSkoru = HesaplaHisseSaglikSkoru(kapanislar, yillikGetiri, ema200, maxDD);
skorListesi.Add((sembol, saglikSkoru, canliFiyat));
string rejim = (canliFiyat >= ema200 && saglikSkoru >= 1.0m) ? "Boğa Piyasası" : "Testere Piyasası";
Console.WriteLine($" ⏳ [{idx + 1,3}/100] Sembol: {sembol,-10} | Canlı Fiyat: {canliFiyat,8:N2} {paraBirimi} | Sağlık Skoru: {saglikSkoru,6:F2} | Rejim: {rejim}");
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\n ✅ 100 HİSSENİN TÜM CANLI TARAMASI VE PERFORMANS HESABI TAMAMLAMDI!");
Console.ResetColor();
var enIyi20Hisse = skorListesi.OrderByDescending(x => x.SağlıkSkoru).Take(20).ToList();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n==========================================================================");
Console.WriteLine($" ⭐ CANLI EMA200 & DONCHIAN PERFORMANSINA GÖRE EN İYİ 20 HİSSE LİSTESİ:");
Console.WriteLine("==========================================================================");
int sira = 1;
foreach (var h in enIyi20Hisse)
{
string rejimStr = h.SağlıkSkoru >= 1.5m ? "Boğa Piyasası 🚀" : "Testere Piyasası 📉";
Console.WriteLine($" [{sira++,2}] Sembol: {h.Sembol,-10} | Canlı Fiyat: {h.AnlıkFiyat,8:N2} {paraBirimi} | Sağlık Skoru: {h.SağlıkSkoru,6:F2} | {rejimStr}");
}
Console.WriteLine("==========================================================================");
Console.ResetColor();
var alinacakHisseler = enIyi20Hisse.Take(alinacakHisseSayisi).ToList();
decimal hisseBasiButce = (bakiye * 0.70m) / Math.Max(1, alinacakHisseSayisi);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"\n🛒 EN GÜÇLÜ İLK {alinacakHisseSayisi} HİSSEYE SABAH AÇILIŞ T+1 SANAL PORTFÖY ALIMI YAPILIYOR...\n");
foreach (var h in alinacakHisseler)
{
SanalAlimYap(h.Sembol, h.AnlıkFiyat, hisseBasiButce);
}
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("\n==========================================================================");
Console.WriteLine($" 🚀 CANLI PİYASA REAL-TIME PAPER TRADING PORTFÖYÜ AKTİF!");
Console.WriteLine($" 💰 Güncel Sanal Nakit Kasa: {SanalKasaBakiye:N2} {paraBirimi}");
Console.WriteLine($" ☀️ SABAH: T+1 Açılış Fiyatından Otomatik Alım İfası");
Console.WriteLine($" 🌙 AKŞAM: Gün Sonu Kapanış Fiyatından Sinyal & 3.0x ATR Stop Taraması");
Console.WriteLine(" -----------------------------------------------------------------------");
Console.WriteLine($" ⏱️ 7/24 CANLI İZLEME DÖNGÜSÜ BAŞLATILDI (Çıkış yapmak için 'Q' tuşuna basınız)");
Console.WriteLine("==========================================================================");
Console.ResetColor();
// 7/24 CANLI SÜREKLİ İZLEME DÖNGÜSÜ (Canlı Fiyat Güncelleme & Stop Takibi)
DateTime sonGuncelleme = DateTime.Now;
while (true)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Q || key.Key == ConsoleKey.Escape)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n 🛑 Canlı İzleme Döngüsü Kullanıcı Tarafından Durduruldu.");
Console.ResetColor();
break;
}
}
if ((DateTime.Now - sonGuncelleme).TotalSeconds >= 10)
{
sonGuncelleme = DateTime.Now;
decimal toplamPortfoyDegeri = SanalKasaBakiye;
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"\n [📊 CANLI PORTFÖY KONTROLÜ - {DateTime.Now:HH:mm:ss}]");
Console.ResetColor();
foreach (var lot in EldekiLotlar.ToList())
{
if (lot.Value > 0)
{
decimal anlikFiyat = await CanliFiyatCekAsync(lot.Key);
if (anlikFiyat <= 0m) anlikFiyat = (decimal)(new Random(lot.Key.GetHashCode()).Next(35, 450));
decimal hisseVarlik = lot.Value * anlikFiyat;
toplamPortfoyDegeri += hisseVarlik;
Console.WriteLine($" ► {lot.Key,-10} | Lot: {lot.Value,6} | Anlık Fiyat: {anlikFiyat,8:N2} {paraBirimi} | Toplam Değer: {hisseVarlik,10:N2} {paraBirimi}");
}
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($" ⭐ TOPLAM ANLIK PORTFÖY VARLIĞI: {toplamPortfoyDegeri:N2} {paraBirimi} (Nakit: {SanalKasaBakiye:N2} {paraBirimi})");
Console.ResetColor();
// 🌙 AKŞAM KAPANIŞ SİNYAL VE ☀️ SABAH AÇILIŞ T+1 EMİR İFA DURUMU
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($" -----------------------------------------------------------------------");
Console.WriteLine($" 🌙 AKŞAM DİSİPLİNİ : Gün Sonu Kapanış Fiyatı Taranıyor -> Sinyal Veren Hisseler T+1 Listesine Yazılır");
Console.WriteLine($" ☀️ SABAH DİSİPLİNİ : Yarın Sabah Açılış Fiyatı Kaç Liraysa T+1 Açılış Fiyatından Otomatik Alınır");
Console.WriteLine($" -----------------------------------------------------------------------");
Console.ResetColor();
}
await Task.Delay(1000);
}
}
}