markaz_arshy/clean_history_csv.py
2025-08-12 14:36:24 +00:00

108 lines
4.2 KiB
Python

# clean_history_csv.py
#
# Deskripsi:
# Skrip ini membaca file 'history.csv' yang diekspor dari MT5,
# membersihkan nama kolom yang tidak standar, memperbaiki format angka,
# dan menyimpannya sebagai file baru yang rapi bernama 'history_cleaned.csv'.
import pandas as pd
import logging
import re
# --- Konfigurasi ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
INPUT_FILE = 'history.csv'
OUTPUT_FILE = 'history_cleaned.csv'
def clean_numeric_value(value):
"""Membersihkan string angka dari berbagai format secara robust."""
if pd.isna(value):
return None
if isinstance(value, (int, float)):
return value
if isinstance(value, str):
try:
# Hapus semua spasi
s = str(value).strip().replace(' ', '')
# Hitung jumlah titik
dots = s.count('.')
# Jika ada lebih dari satu titik, anggap sebagai pemisah ribuan
# dan hapus semua kecuali yang terakhir.
if dots > 1:
s = s.replace('.', '', dots - 1)
return float(s)
except (ValueError, TypeError):
return None # Kembalikan None jika konversi gagal
return None
def main():
"""Fungsi utama untuk membersihkan file CSV."""
try:
df = pd.read_csv(INPUT_FILE, on_bad_lines='skip')
logging.info(f"Berhasil membaca {len(df)} baris dari '{INPUT_FILE}'.")
except FileNotFoundError:
logging.error(f"File '{INPUT_FILE}' tidak ditemukan. Pastikan file ada di direktori yang sama.")
return
except Exception as e:
logging.error(f"Gagal membaca file CSV: {e}")
return
# Menghapus kolom terakhir jika kosong (sering terjadi saat ekspor dari MT5)
if df.columns[-1].startswith('Unnamed'):
df = df.iloc[:, :-1]
original_columns = df.columns.tolist()
# Membersihkan nama kolom: huruf kecil, ganti spasi dengan _, hapus karakter aneh
df.columns = [re.sub(r'\.\d+$', '', col).strip().lower().replace(' ', '_').replace('/', '') for col in original_columns]
# Menangani kolom duplikat ('Time', 'Price') dari ekspor MT5
cols = df.columns.tolist()
time_indices = [i for i, name in enumerate(cols) if name == 'time']
price_indices = [i for i, name in enumerate(cols) if name == 'price']
if len(time_indices) > 1:
cols[time_indices[0]] = 'open_time'
cols[time_indices[1]] = 'close_time'
if len(price_indices) > 1:
cols[price_indices[0]] = 'open_price'
cols[price_indices[1]] = 'close_price'
df.columns = cols
logging.info(f"Nama kolom asli: {original_columns}")
logging.info(f"Nama kolom distandarkan: {df.columns.tolist()}")
# Mengganti nama 'position' menjadi 'ticket' untuk konsistensi
if 'position' in df.columns:
df.rename(columns={'position': 'ticket'}, inplace=True)
logging.info("Mengganti nama kolom 'position' menjadi 'ticket'.")
# Membersihkan kolom-kolom numerik
numeric_cols = ['open_price', 'close_price', 'profit', 'volume', 'commission', 'swap', 's_l', 't_p']
for col in numeric_cols:
if col in df.columns:
df[col] = df[col].apply(clean_numeric_value)
# Menghapus baris di mana data penting gagal dibersihkan
df.dropna(subset=['open_price', 'profit', 'ticket'], inplace=True)
df['ticket'] = df['ticket'].astype(int)
logging.info(f"Jumlah baris setelah pembersihan data numerik: {len(df)}.")
# Memilih dan menyusun ulang kolom-kolom penting
final_cols_order = [
'ticket', 'open_time', 'symbol', 'type', 'volume', 'open_price', 's_l', 't_p',
'close_time', 'close_price', 'commission', 'swap', 'profit'
]
# Filter hanya kolom yang ada di dataframe
existing_cols = [col for col in final_cols_order if col in df.columns]
cleaned_df = df[existing_cols]
try:
cleaned_df.to_csv(OUTPUT_FILE, index=False)
logging.info(f"Berhasil! {len(cleaned_df)} baris data yang bersih telah disimpan ke '{OUTPUT_FILE}'.")
except Exception as e:
logging.error(f"Gagal menyimpan file yang sudah dibersihkan: {e}")
if __name__ == '__main__':
main()