-AnonymousD-

analisis

Apr 11th, 2025
622
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.99 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import requests
  3. import json
  4. import pandas as pd
  5. import matplotlib.pyplot as plt
  6. import matplotlib.dates as mdates
  7. import asyncio
  8. from datetime import datetime
  9. from mplfinance.original_flavor import candlestick_ohlc
  10. from telegram import Update, ReplyKeyboardMarkup
  11. from telegram.ext import (
  12.     Application,
  13.     CommandHandler,
  14.     MessageHandler,
  15.     filters,
  16.     ContextTypes
  17. )
  18.  
  19. class CryptoAnalyzer:
  20.     def __init__(self):
  21.         self.config = self.load_config()
  22.         self.base_url = "https://indodax.com/api"
  23.         self.scheduler = None
  24.  
  25.     """=======================
  26.    MODUL KONFIGURASI
  27.    ======================="""
  28.     def load_config(self):
  29.         try:
  30.             with open('config.json') as f:
  31.                 return json.load(f)
  32.         except Exception as e:
  33.             print(f"Error loading config: {e}")
  34.             exit(1)
  35.  
  36.     """=======================
  37.    MODUL DATA MARKET
  38.    ======================="""
  39.     def fetch_market_data(self, pair='btc_idr', timeframe='1h', limit=100):
  40.         """Ambil data OHLC dari API Indodax"""
  41.         try:
  42.             response = requests.get(f"{self.base_url}/{pair}/trades")
  43.             response.raise_for_status()
  44.             trades = response.json()
  45.            
  46.             df = pd.DataFrame(trades)
  47.             df['date'] = pd.to_datetime(df['date'].astype(float), unit='s')
  48.             df = df.set_index('date')
  49.             return df['price'].resample(timeframe).ohlc().reset_index()
  50.         except Exception as e:
  51.             print(f"Error fetching data: {e}")
  52.             return None
  53.  
  54.  
  55.     """=======================
  56.    MODUL ANALISIS TEKNIKAL
  57.    ======================="""
  58.     def detect_patterns(self, ohlc_data):
  59.         patterns = []
  60.    
  61.         if len(ohlc_data) < 5:  # Minimum 5 candle untuk analisis
  62.             return patterns
  63.  
  64.     # Prepare data
  65.         closes = ohlc_data['close'].values
  66.         highs = ohlc_data['high'].values
  67.         lows = ohlc_data['low'].values
  68.         opens = ohlc_data['open'].values
  69.    
  70.         # 1. Pola Reversal Bearish
  71.         if self._is_double_top(highs):
  72.             patterns.append('Bearish Double Top')
  73.         if self._is_head_and_shoulders(highs, lows):
  74.             patterns.append('Bearish Head and Shoulders')
  75.         if self._is_rising_wedge(ohlc_data):
  76.             patterns.append('Bearish Rising Wedge')
  77.         if self._is_expanding_triangle(highs, lows, bearish=True):
  78.             patterns.append('Bearish Expanding Triangle')
  79.         if self._is_triple_top(highs):
  80.             patterns.append('Bearish Triple Top')
  81.  
  82.         # 2. Pola Reversal Bullish
  83.         if self._is_double_bottom(lows):
  84.             patterns.append('Bullish Double Bottom')
  85.         if self._is_inverse_head_and_shoulders(highs, lows):
  86.             patterns.append('Bullish Inverted H&S')
  87.         if self._is_falling_wedge(ohlc_data):
  88.             patterns.append('Bullish Falling Wedge')
  89.         if self._is_expanding_triangle(highs, lows, bearish=False):
  90.             patterns.append('Bullish Expanding Triangle')
  91.         if self._is_triple_bottom(lows):
  92.             patterns.append('Bullish Triple Bottom')
  93.  
  94.     # 3. Pola Continuation
  95.         if self._is_bullish_flag(ohlc_data):
  96.             patterns.append('Bullish Flag')
  97.         if self._is_bullish_pennant(ohlc_data):
  98.             patterns.append('Bullish Pennant')
  99.         if self._is_ascending_triangle(highs, lows):
  100.             patterns.append('Ascending Triangle')
  101.         if self._is_descending_triangle(highs, lows):
  102.             patterns.append('Descending Triangle')
  103.         if self._is_symmetrical_triangle(highs, lows):
  104.             patterns.append('Symmetrical Triangle')
  105.  
  106.         # 4. Pola Candlestick (3 candle terakhir)
  107.         if len(ohlc_data) >= 3:
  108.             latest_candles = ohlc_data.iloc[-3:]
  109.             patterns.extend(self._detect_candlestick_patterns(latest_candles))
  110.  
  111.         return patterns
  112.  
  113. """=======================
  114.    MODUL ANALISIS TEKNIKAL - POLA UTAMA
  115.    ======================="""
  116.  
  117.     def _is_double_top(self, highs, lookback=20, tolerance=0.02):
  118.         if len(highs) < lookback:
  119.             return False
  120.         peak1 = max(highs[-lookback:-lookback//2])
  121.         peak2 = max(highs[-lookback//2:])
  122.         return abs(peak1 - peak2) < tolerance * peak1
  123.  
  124.     def _is_head_and_shoulders(self, highs, lows, lookback=30):
  125.         """Deteksi Head and Shoulders pattern"""
  126.         if len(highs) < lookback:
  127.             return False
  128.        
  129.         left_shoulder = max(highs[-lookback:-lookback//2])
  130.         head = max(highs[-lookback//2:-lookback//4])
  131.         right_shoulder = max(highs[-lookback//4:])
  132.    
  133.         neckline = (min(lows[-lookback:-lookback//2]) + min(lows[-lookback//4:])) / 2
  134.                
  135.         return (left_shoulder < head and right_shoulder < head and right_shoulder > neckline and left_shoulder > neckline)
  136.  
  137.         # Implement other pattern detection methods similarly...  
  138.  
  139.  
  140. """=======================
  141.    DETEKSI POLA CHART
  142.    ======================="""
  143.  
  144.     def _is_double_top(self, highs, lookback=20, tolerance=0.02):
  145.         """Detect double top pattern"""
  146.         if len(highs) < lookback:
  147.             return False
  148.         peak1 = max(highs[-lookback:-lookback//2])
  149.         peak2 = max(highs[-lookback//2:])
  150.         return abs(peak1 - peak2) < tolerance * peak1
  151.  
  152.     def _is_head_and_shoulders(self, highs, lows, lookback=30):
  153.         # Implementasi sederhana H&S pattern
  154.         if len(highs) < lookback:
  155.             return False
  156.            
  157.         left_shoulder = highs[-lookback:-lookback//2].max()
  158.         head = highs[-lookback//2:-lookback//4].max()
  159.         right_shoulder = highs[-lookback//4:].max()
  160.        
  161.         neckline = (lows[-lookback:-lookback//2].min() +
  162.                    lows[-lookback//4:].min()) / 2
  163.                    
  164.         return (left_shoulder < head and right_shoulder < head and
  165.                 right_shoulder > neckline and left_shoulder > neckline)
  166.  
  167.     def _is_rising_wedge(self, ohlc_data, lookback=15):
  168.         highs = ohlc_data['high'].values[-lookback:]
  169.         lows = ohlc_data['low'].values[-lookback:]
  170.        
  171.         # Hitung garis trend
  172.         high_slope = (highs[-1] - highs[0]) / lookback
  173.         low_slope = (lows[-1] - lows[0]) / lookback
  174.        
  175.         return high_slope > low_slope > 0 and (highs[-1] - lows[-1]) < (highs[0] - lows[0])
  176.  
  177.     """=======================
  178.    DETEKSI POLA CANDLESTICK
  179.    ======================="""
  180.     def detect_patterns(self, ohlc_data):
  181.         """Detect all technical patterns"""
  182.         patterns = []
  183.    
  184.         if len(ohlc_data) < 5:  # Minimum 5 candles needed
  185.             return patterns
  186.  
  187.         # Prepare data
  188.         closes = ohlc_data['close'].values
  189.         highs = ohlc_data['high'].values
  190.         lows = ohlc_data['low'].values
  191.         opens = ohlc_data['open'].values
  192.  
  193.         # Bearish Patterns
  194.         if self._is_double_top(highs):
  195.             patterns.append('Bearish Double Top')
  196.         if self._is_head_and_shoulders(highs, lows):
  197.             patterns.append('Bearish Head and Shoulders')
  198.  
  199.         # Bullish Patterns  
  200.         if self._is_double_bottom(lows):
  201.             patterns.append('Bullish Double Bottom')
  202.         if self._is_inverse_head_and_shoulders(highs, lows):
  203.             patterns.append('Bullish Inverted H&S')
  204.  
  205.         # Candlestick Patterns (last 3 candles)
  206.         if len(ohlc_data) >= 3:
  207.             latest = ohlc_data.iloc[-3:]
  208.             if self._is_three_black_crows(latest):
  209.                 patterns.append('Three Black Crows')
  210.             if self._is_morning_star(latest.iloc[0], latest.iloc[1], latest.iloc[2]):
  211.                 patterns.append('Morning Star')
  212.  
  213.         return patterns
  214.  
  215. def _is_double_top(self, highs, lookback=20, tolerance=0.02):
  216.     """Detect double top pattern"""
  217.     if len(highs) < lookback:
  218.         return False
  219.     peak1 = max(highs[-lookback:-lookback//2])
  220.     peak2 = max(highs[-lookback//2:])
  221.     return abs(peak1 - peak2) < tolerance * peak1
  222.  
  223. def _is_double_bottom(self, lows, lookback=20, tolerance=0.02):
  224.     """Detect double bottom pattern"""
  225.     if len(lows) < lookback:
  226.         return False
  227.     trough1 = min(lows[-lookback:-lookback//2])
  228.     trough2 = min(lows[-lookback//2:])
  229.     return abs(trough1 - trough2) < tolerance * trough1
  230.  
  231. def _is_three_black_crows(self, candles):
  232.     """Detect three black crows pattern"""
  233.     return (all(c['close'] < c['open'] for c in candles) and
  234.             candles.iloc[0]['open'] > candles.iloc[1]['open'] > candles.iloc[2]['open'] and
  235.             candles.iloc[0]['close'] > candles.iloc[1]['close'] > candles.iloc[2]['close'])
  236.  
  237. def _is_morning_star(self, c1, c2, c3):
  238.     """Detect morning star pattern"""
  239.     return (c1['close'] < c1['open'] and  # First candle is bearish
  240.             abs(c2['close'] - c2['open']) < 0.01 * c2['open'] and  # Second is doji
  241.             c3['close'] > c3['open'] and  # Third is bullish
  242.             c3['close'] > c1['close'])  # Closes above first candle
  243.     def _is_evening_star(self, c1, c2, c3):
  244.         return (c1['close'] > c1['open'] and  # Candle hijau
  245.                 abs(c2['close'] - c2['open']) < 0.01 * c2['open'] and  # Doji
  246.                 c3['close'] < c3['open'] and  # Candle merah
  247.                 c3['close'] < c1['close'] * 0.98)  # Penutupan di bawah 98% sebelumnya
  248.  
  249.     def _is_three_black_crows(self, candles):
  250.         return all(c['close'] < c['open'] for c in candles) and (
  251.             candles[0]['open'] > candles[1]['open'] > candles[2]['open'] and
  252.             candles[0]['close'] > candles[1]['close'] > candles[2]['close'])
  253.  
  254.     """=======================
  255.    MODUL VISUALISASI
  256.    ======================="""
  257.     def create_chart(self, ohlc_data, patterns=None):
  258.         """Buat grafik candlestick dengan anotasi pola"""
  259.         plt.figure(figsize=(14, 7))
  260.         ax = plt.subplot()
  261.        
  262.         # Plot candlestick
  263.         ohlc_data['date_num'] = mdates.date2num(ohlc_data['date'])
  264.         candlestick_ohlc(
  265.             ax,
  266.             ohlc_data[['date_num', 'open', 'high', 'low', 'close']].values,
  267.             width=0.6,
  268.             colorup='#27ae60',
  269.             colordown='#c0392b'
  270.         )
  271.        
  272.         # Anotasi untuk pola terdeteksi
  273.         if patterns:
  274.             self._annotate_patterns(ax, ohlc_data, patterns)
  275.        
  276.         ax.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m %H:%M'))
  277.         plt.xticks(rotation=45)
  278.         plt.title('Analisis BTC/IDR - ' + datetime.now().strftime('%d %b %Y'))
  279.         plt.tight_layout()
  280.        
  281.         chart_path = 'latest_chart.png'
  282.         plt.savefig(chart_path, dpi=100)
  283.         plt.close()
  284.         return chart_path
  285.  
  286.     def _annotate_patterns(self, ax, ohlc_data, patterns):
  287.         """Tambahkan anotasi pola ke chart"""
  288.         for pattern in patterns:
  289.             if 'Double Top' in pattern:
  290.                 self._mark_double_top(ax, ohlc_data)
  291.             elif 'Head and Shoulders' in pattern:
  292.                 self._mark_head_and_shoulders(ax, ohlc_data)
  293.             # Tambahkan anotasi untuk pola lainnya...
  294.     """=======================
  295.    MODUL LAPORAN
  296.    ======================="""
  297.    def generate_report(self, patterns, ohlc_data):
  298.         """Buat laporan analisis dengan klasifikasi pola"""
  299.         current_price = ohlc_data.iloc[-1]['close']
  300.        
  301.         report = {
  302.             'timestamp': datetime.now().strftime('%d-%m-%Y %H:%M'),
  303.             'current_price': f"Rp {current_price:,.0f}",
  304.             'volatility': f"{self._calculate_volatility(ohlc_data):.2f}%",
  305.             'patterns': self._classify_patterns(patterns),
  306.             'recommendation': self._generate_recommendation(patterns)
  307.         }
  308.         return report
  309.  
  310.     def _classify_patterns(self, patterns):
  311.         """Klasifikasikan pola berdasarkan jenisnya"""
  312.         classified = {
  313.             'Reversal Bullish': [],
  314.             'Reversal Bearish': [],
  315.             'Continuation': [],
  316.             'Candlestick': []
  317.         }
  318.        
  319.         pattern_types = {
  320.             'Bullish Double Bottom': 'Reversal Bullish',
  321.             'Bullish Inverted H&S': 'Reversal Bullish',
  322.             'Morning Star': 'Candlestick',
  323.             'Bearish Double Top': 'Reversal Bearish',
  324.             'Bearish Head and Shoulders': 'Reversal Bearish',
  325.             'Evening Star': 'Candlestick',
  326.             'Bullish Flag': 'Continuation',
  327.             'Ascending Triangle': 'Continuation'
  328.             # Tambahkan mapping lainnya...
  329.         }
  330.        
  331.         for pattern in patterns:
  332.             for p_type, p_list in pattern_types.items():
  333.                 if p_type in pattern:
  334.                     classified[p_list].append(pattern)
  335.                     break
  336.        
  337.         return classified
  338.  
  339.     def _generate_recommendation(self, patterns):
  340.         """Buat rekomendasi berdasarkan pola terdeteksi"""
  341.         strength = 0
  342.         for pattern in patterns:
  343.             if 'Bullish' in pattern:
  344.                 strength += 1
  345.             elif 'Bearish' in pattern:
  346.                 strength -= 1
  347.        
  348.         if strength >= 3:
  349.             return "🟢 STRONG BUY (Bullish Strong)"
  350.         elif strength >= 1:
  351.             return "🟢 BUY (Bullish)"
  352.         elif strength <= -3:
  353.             return "🔴 STRONG SELL (Bearish Strong)"
  354.         elif strength <= -1:
  355.             return "🔴 SELL (Bearish)"
  356.         return "🟡 HOLD (Neutral)"
  357.  
  358.  
  359.     """=======================
  360.    MODUL TELEGRAM
  361.    ======================="""
  362.     async def send_report(self, context):
  363.         """Kirim laporan ke Telegram"""
  364.         try:
  365.             # Dapatkan data dan buat laporan
  366.             ohlc_data = self.fetch_market_data()
  367.             patterns = self.detect_patterns(ohlc_data)
  368.             chart_path = self.create_chart(ohlc_data)
  369.             report = self.generate_report(patterns, ohlc_data)
  370.            
  371.             # Format pesan
  372.             message = (
  373.                 f"🕒 **Laporan {report['timestamp']}**\n"
  374.                 f"📊 Pola Terdeteksi: {', '.join(report['patterns']) or 'Tidak ada'}\n"
  375.                 f"💰 Harga Terkini: {report['current_price']}\n"
  376.                 f"📈 Volatilitas: {report['volatility']}\n"
  377.                 f"📌 Rekomendasi: {report['recommendation']}"
  378.             )
  379.            
  380.             # Kirim melalui Telegram
  381.             await context.bot.send_photo(
  382.                 chat_id=self.config['telegram']['chat_id'],
  383.                 photo=open(chart_path, 'rb'),
  384.                 caption=message,
  385.                 parse_mode='Markdown'
  386.             )
  387.         except Exception as e:
  388.             print(f"Error sending report: {e}")
  389.  
  390.     """=======================
  391.    MODUL SCHEDULER
  392.    ======================="""
  393.     async def schedule_updates(self, context):
  394.         """Jadwalkan pengiriman setiap 1 jam"""
  395.         while True:
  396.             await self.send_report(context)
  397.             await asyncio.sleep(3600)  # 1 jam
  398.  
  399.     async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
  400.         """Handler command /start"""
  401.         await update.message.reply_text(
  402.             "Bot Analisis Crypto Aktif!\n"
  403.             "Laporan akan dikirim otomatis setiap 1 jam",
  404.             reply_markup=self._main_menu()
  405.         )
  406.         # Mulai scheduler
  407.         asyncio.create_task(self.schedule_updates(context))
  408.  
  409.     def _main_menu(self):
  410.         """Tampilan menu utama"""
  411.         return ReplyKeyboardMarkup(
  412.             [["🔄 Update Sekarang", "⚙️ Settings"]],
  413.             resize_keyboard=True
  414.         )
  415.  
  416.     """=======================
  417.    MAIN PROGRAM
  418.    ======================="""
  419.     def run(self):
  420.  
  421.         application = Application.builder().token(self.config['telegram']['token']).build()
  422.        
  423.         # Registrasi handler
  424.         application.add_handler(CommandHandler("start", self.start))
  425.         application.add_handler(MessageHandler(filters.Regex("🔄 Update Sekarang"), self.send_report))
  426.        
  427.         application.run_polling()
  428.  
  429. if __name__ == "__main__":
  430.     analyzer = CryptoAnalyzer()
  431.     analyzer.run()
Advertisement
Add Comment
Please, Sign In to add comment