Layanan Cloud Amazon dan Analisis Portofolio Investasi

Baru-baru ini, ada volatilitas tinggi di pasar saham, ketika, misalnya, sebuah makalah yang stabil dari sebuah perusahaan terkenal dapat kehilangan beberapa persen sekaligus pada berita sanksi terhadap manajemennya atau sebaliknya melambung ke langit pada laporan positif dan harapan investor tentang dividen super-menguntungkan.

Bagaimana menentukan apakah kepemilikan sekuritas tertentu telah menghasilkan pendapatan atau hanya kerugian dan kekecewaan?

(Sumber)

Dalam artikel ini saya akan memberi tahu Anda bagaimana mengidentifikasi dan memvisualisasikan hasil keuangan yang disesuaikan untuk efek.

Dengan menggunakan contoh pelaporan klien Membuka Pialang, kami akan mempertimbangkan penguraian dan konsolidasi laporan pialang untuk pasar saham, membangun arsitektur sistem pelaporan awan dengan analisis sederhana dan nyaman selanjutnya di AWS Quicksight.

Deskripsi tugas


Banyak pelatihan dan pelajaran pelatihan memberi tahu kami tentang perlunya jurnal trader, di mana semua parameter transaksi dicatat untuk analisis lebih lanjut dan merangkum hasil dari strategi perdagangan. Saya setuju bahwa pendekatan ini untuk bekerja di Bursa memungkinkan Anda mendisiplinkan seorang pedagang, meningkatkan kesadarannya, tetapi juga dapat membuat Anda lelah dari proses yang membosankan.

Saya akui bahwa pada awalnya saya berusaha dengan hati-hati mengikuti saran penjurnalan, dengan cermat menuliskan setiap transaksi dengan parameter-parameternya dalam tabel Excel, membuat beberapa laporan, bagan ringkasan, merencanakan transaksi di masa depan, tetapi ... Saya segera bosan dengan semuanya.

Mengapa menyimpan jurnal trader secara manual tidak nyaman
  • pengisian jurnal secara manual (bahkan menggunakan otomatisasi parsial, dalam bentuk pembongkaran transaksi harian dari terminal perdagangan) dengan cepat ban;
  • ada risiko tinggi kesalahan atau kesalahan ketik dengan entri manual;
  • mungkin terjadi bahwa pedagang aktif menjadi investor pasif dan dia kembali ke majalah ini semakin sedikit, dan kemudian sepenuhnya melupakannya (kasus saya); baik dan akhirnya
  • kita dapat memprogram, mengapa tidak mengambil keuntungan dari ini dan mengotomatisasi seluruh proses? Jadi, ayo pergi!

Seringkali, perusahaan pialang adalah organisasi teknologi tinggi yang memberikan analisis analitik berkualitas tinggi kepada hampir semua kliennya tentang hampir semua masalah. Adalah adil untuk mengatakan bahwa pelaporan ini menjadi semakin baik dengan setiap pembaruan, tetapi bahkan yang paling canggih sekalipun mungkin tidak memiliki penyesuaian dan konsolidasi yang ingin dilihat oleh pelanggan yang ingin tahu dan ingin tahu.

Misalnya, Pialang Pembukaan memungkinkan Anda untuk menerima laporan pialang dalam format XML di akun pribadi Anda, tetapi jika Anda memiliki IIA dan akun pialang biasa di Moscow Stock Exchange (MOEX), ini akan menjadi dua laporan yang berbeda, dan jika Anda memiliki akun lain di St. Petersburg Stock Exchange (SPB), maka dua yang pertama akan menambah satu lagi.

Secara total, untuk mendapatkan jurnal konsolidasi investor, perlu untuk memproses tiga file dalam format XML.

Laporan yang disebutkan di atas tentang MOEX dan SPB sedikit berbeda dalam formatnya, yang perlu dipertimbangkan dalam proses penerapan pemetaan data.

Arsitektur sistem dalam pengembangan


Diagram di bawah ini menunjukkan model arsitektur sistem yang sedang dikembangkan:


Implementasi Parser


Kami akan menerima laporan pada ketiga akun di Akun Pribadi untuk periode maksimum yang mungkin (dapat dibagi menjadi beberapa laporan untuk setiap tahun), menyimpannya dalam format XML dan menempatkannya dalam satu folder. Sebagai data uji untuk penelitian ini, kami akan menggunakan portofolio klien fiktif, tetapi dengan parameter sedekat mungkin dengan realitas pasar.


Misalkan investor Mr X sedang dipertimbangkan memiliki portofolio kecil dari lima sekuritas:

  1. Laporan pertukaran SPB akan memiliki dua makalah: Apple dan Microsoft;
  2. Laporan tentang pertukaran MOEX (broker) berisi satu makalah: FGC UES;
  3. Laporan di MOEX Exchange (IIS) berisi dua sekuritas: MMK dan OFZ 24019;

Menurut lima sekuritas kami, mungkin ada transaksi pembelian / penjualan, pembayaran dividen dan kupon, harga dapat berubah, dll. Kami ingin melihat situasi saat ini, yaitu: hasil keuangan, dengan memperhitungkan semua pembayaran, transaksi, dan nilai pasar saat ini.

Dan di sini Python berperan, kami membaca informasi dari semua laporan menjadi satu array:

my_files_list = [join('Data/', f) for f in listdir('Data/') if isfile(join('Data/', f))] my_xml_data = [] #     for f in my_files_list: tree = ET.parse(f) root = tree.getroot() my_xml_data.append(root) 

Untuk analitik, dari laporan kami memerlukan beberapa entitas, yaitu:

  • Posisi sekuritas dalam portofolio;
  • Kesepakatan akhir;
  • Operasi non-perdagangan dan pergerakan akun lainnya;
  • Harga rata-rata posisi terbuka
Untuk menyiapkan sampel, kami akan menggunakan empat kamus untuk menggambarkan set di atas.

 dict_stocks = {'stock_name': [], 'account': [], 'currency': [], 'current_cost': [], 'current_cost_rub': [], 'saldo' : []} dict_deals = {'stock_name': [], 'account': [], 'date_oper': [], 'type_oper': [], 'quantity': [], 'price': [], 'currency': [], 'brokerage': [], 'result': []} dict_flows = {'stock_name': [], 'account': [], 'date_oper': [], 'type_oper': [], 'result': [], 'currency': []} dict_avg_price = {'stock_name': [], 'account': [], 'avg_open_price' : []} 

Beberapa kata tentang kamus ini.

Kamus Dict_stocks
Kamus dict_stocks diperlukan untuk menyimpan informasi umum tentang portofolio:

  • Nama kertas (stock_name);
  • Nama akun (SPB, MOEX BROK, MOEX IIS) (akun);
  • Mata uang yang digunakan untuk penyelesaian pada makalah ini (mata uang);
  • Nilai saat ini (pada saat menghasilkan laporan di Pialang Pembukaan Akun Pribadi) (current_cost). Di sini saya ingin mencatat bahwa untuk pelanggan yang terlalu menuntut, dimungkinkan untuk melakukan perbaikan tambahan di masa depan dan menggunakan tanda terima dinamis dari kutipan keamanan dari terminal perdagangan atau dari situs web pertukaran yang sesuai;
  • Nilai posisi keamanan saat ini pada saat laporan dihasilkan (current_cost_rub)
    Demikian pula dengan item di atas, di sini Anda juga bisa mendapatkan kurs Bank Sentral pada saat ini atau kurs, sesuka Anda.
  • Saldo surat berharga saat ini (saldo)

Kamus dict_deals
Kamus dict_deals diperlukan untuk menyimpan informasi berikut tentang transaksi yang diselesaikan:

  • Nama kertas (stock_name);
  • Nama akun (SPB, MOEX BROK, MOEX IIS) (akun);
  • Tanggal transaksi, mis. T0 (date_oper);
  • Jenis operasi (type_oper);
  • Volume sekuritas yang berpartisipasi dalam transaksi (kuantitas);
  • Harga di mana transaksi dilakukan (harga);
  • Mata uang tempat transaksi dilakukan (mata uang);
  • Komisi pialang untuk transaksi (pialang);
  • Hasil keuangan dari transaksi (hasil)

Kamus Dict_flows
Kamus dict_flows mencerminkan pergerakan dana pada akun klien dan digunakan untuk menyimpan informasi berikut:

  • Nama kertas (stock_name);
  • Nama akun (SPB, MOEX BROK, MOEX IIS) (akun);
  • Tanggal transaksi, mis. T0 (date_oper);
  • Jenis operasi (type_oper). Ini dapat mengambil beberapa nilai: div, NKD, pajak;
  • Mata uang tempat transaksi dilakukan (mata uang);
  • Hasil keuangan dari operasi (hasil)

Kamus dict_avg_harga
Kamus dict_avg_price diperlukan untuk informasi akuntansi dengan harga pembelian rata-rata untuk setiap makalah:

  • Nama kertas (stock_name);
  • Nama akun (SPB, MOEX BROK, MOEX IIS) (akun);
  • Harga rata-rata posisi terbuka (avg_open_price)

Kami memproses berbagai dokumen XML dan mengisi kamus-kamus ini dengan data yang sesuai:

 #       for XMLdata in my_xml_data: #      exchange_name = 'SPB' if XMLdata.get('board_list') == ' ' else 'MOEX' client_code = XMLdata.get('client_code') account_name = get_account_name(exchange_name, client_code) #   current_position, deals, flows, stock_name, \ saldo, ticketdate, price, brokerage, \ operationdate, currency, \ current_cost, current_cost_rub, \ stock_name_deal, payment_currency, currency_flows = get_allias(exchange_name) #      get_briefcase(XMLdata) df_stocks = pd.DataFrame(dict_stocks) df_stocks.set_index("stock_name", drop = False, inplace = True) #    get_deals(XMLdata) df_deals = pd.DataFrame(dict_deals) df_avg = pd.DataFrame(dict_avg_price) #       get_nontrade_operation(XMLdata) df_flows = pd.DataFrame(dict_flows) 

Semua pemrosesan melewati loop atas semua data XML dari laporan. Informasi tentang platform perdagangan, kode klien sama di semua laporan, sehingga Anda dapat dengan aman mengekstraknya dari tag yang sama tanpa menggunakan pemetaan.

Tetapi kemudian kita harus menggunakan desain khusus yang akan memberikan alias yang diperlukan untuk tag berdasarkan laporan (SPB atau MOEX), karena identik dalam sifat data dalam laporan ini disebut berbeda.

Tandai perbedaan
  • Komisi broker transaksi dalam laporan SBP terletak pada tag broker , dan dalam laporan MOEX - broker_commission ;
  • Tanggal transaksi akun non-perdagangan dalam laporan SPB adalah tanggal operasi , dan dalam MOEX, itu adalah tanggal operasi , dll.

Contoh Pemetaan Tag
 tags_mapping = { 'SPB': { 'current_position': 'briefcase_position', 'deals': 'closed_deal', 'flows': 'nontrade_money_operation', ... 'stock_name_deal': 'issuername', 'paymentcurrency': 'paymentcurrency', 'currency_flows': 'currencycode' }, 'MOEX': { 'current_position': 'spot_assets', 'deals': 'spot_main_deals_conclusion', 'flows': 'spot_non_trade_money_operations', ... 'stock_name_deal': 'security_name', 'paymentcurrency': 'price_currency_code', 'currency_flows': 'currency_code' } } 

Fungsi get_allias mengembalikan nama tag yang diperlukan untuk diproses, dengan mengambil nama platform perdagangan sebagai input:

Fungsi Get_allias
 def get_allias(exchange_name): return( tags_mapping[exchange_name]['current_position'], tags_mapping[exchange_name]['deals'], tags_mapping[exchange_name]['flows'], ... tags_mapping[exchange_name]['stock_name_deal'], tags_mapping[exchange_name]['paymentcurrency'], tags_mapping[exchange_name]['currency_flows'] ) 

Fungsi get_briefcase bertanggung jawab untuk memproses informasi tentang status portofolio klien:

Fungsi Get_briefcase
 def get_briefcase(XMLdata): #         briefcase_position briefcase_position = XMLdata.find(current_position) if not briefcase_position: return try: for child in briefcase_position: stock_name_reduce = child.get(stock_name).upper() stock_name_reduce = re.sub('[,\.]|(\s?INC)|(\s+$)|([-\s]?)', '', stock_name_reduce) dict_stocks['stock_name'].append(stock_name_reduce) dict_stocks['account'].append(account_name) dict_stocks['currency'].append(child.get(currency)) dict_stocks['current_cost'].append(float(child.get(current_cost))) dict_stocks['current_cost_rub'].append(float(child.get(current_cost_rub))) dict_stocks['saldo'].append(float(child.get(saldo))) except Exception as e: print('get_briefcase --> Oops! It seems we have a BUG!', e) 

Selanjutnya, fungsi get_deals mengambil informasi tentang transaksi:

Fungsi Get_deals
 def get_deals(XMLdata): stock_name_proc = '' closed_deal = XMLdata.find(deals) if not closed_deal: return #   SPB    -    , #    MOEX:  ,      #    : if exchange_name == 'SPB': sortchildrenby(closed_deal, stock_name_deal) for child in closed_deal: sortchildrenby(child, stock_name_deal) try: for child in closed_deal: stock_name_reduce = child.get(stock_name_deal).upper() stock_name_reduce = re.sub('[,\.]|(\s?INC)|(\s+$)|([-\s]?)', '', stock_name_reduce) dict_deals['stock_name'].append(stock_name_reduce) dict_deals['account'].append(account_name) dict_deals['date_oper'].append(to_dt(child.get(ticketdate)).strftime('%Y-%m-%d')) current_cost = get_current_cost(stock_name_reduce) #    SPB     - quantity, #   MOEX  : buy_qnty  sell_qnty if exchange_name == 'MOEX': if child.get('buy_qnty'): quantity = float(child.get('buy_qnty')) else: quantity = - float(child.get('sell_qnty')) else: quantity = float(child.get('quantity')) dict_deals['quantity'].append(quantity) dict_deals['price'].append(float(child.get('price'))) dict_deals['type_oper'].append('deal') dict_deals['currency'].append(child.get(payment_currency)) brok_comm = child.get(brokerage) if brok_comm is None: brok_comm = 0 else: brok_comm = float(brok_comm) dict_deals['brokerage'].append(float(brok_comm)) #         if stock_name_proc != stock_name_reduce: if stock_name_proc != '': put_avr_price_in_df(account_name, stock_name_proc, \ pnl.m_net_position, pnl.m_avg_open_price) current_cost = get_current_cost(stock_name_proc) pnl.update_by_marketdata(current_cost) if len(dict_deals['result']) > 0: if exchange_name != 'SPB': dict_deals['result'][-1] = pnl.m_unrealized_pnl * 0.87 -dict_deals['brokerage'][-2] else: dict_deals['result'][-1] = pnl.m_unrealized_pnl - dict_deals['brokerage'][-2] stock_name_proc = stock_name_reduce pnl = PnlSnapshot(stock_name_proc, float(child.get('price')), quantity) dict_deals['result'].append(-1 * brok_comm) else: pnl.update_by_tradefeed(float(child.get('price')), quantity) #  ,   if quantity < 0: if pnl.m_realized_pnl > 0 and exchange_name != 'SPB': pnl_sum = pnl.m_realized_pnl * 0.87 - brok_comm else: pnl_sum = pnl.m_realized_pnl - brok_comm dict_deals['result'].append(float(pnl_sum)) else: pnl.update_by_marketdata(current_cost) dict_deals['result'].append(-1 * brok_comm) put_avr_price_in_df(account_name, stock_name_proc, \ pnl.m_net_position, pnl.m_avg_open_price) current_cost = get_current_cost(stock_name_proc) pnl.update_by_marketdata(current_cost) if len(dict_deals['result']) > 0: if exchange_name != 'SPB': dict_deals['result'][-1] = pnl.m_unrealized_pnl * 0.87 -dict_deals['brokerage'][-2] else: dict_deals['result'][-1] = pnl.m_unrealized_pnl - dict_deals['brokerage'][-2] except Exception as e: print('get_deals --> Oops! It seems we have a BUG!', e) 

Selain memproses array dengan informasi tentang parameter transaksi, harga rata-rata posisi terbuka dan direalisasikan oleh PNL menggunakan metode FIFO juga dihitung di sini. Kelas PnlSnapshot bertanggung jawab untuk perhitungan ini, untuk pembuatan yang dengan modifikasi kecil kode yang disajikan di sini diambil sebagai dasar: perhitungan P&L

Dan akhirnya, yang paling sulit untuk diterapkan adalah fungsi mendapatkan informasi tentang operasi non-perdagangan - get_nontrade_operation . Kompleksitasnya terletak pada kenyataan bahwa dalam blok laporan yang digunakan untuk operasi non-perdagangan, tidak ada informasi yang jelas tentang jenis transaksi dan keamanan yang terikat operasi ini.

Contoh tujuan pembayaran untuk operasi non-perdagangan
Pembayaran dividen atau akumulasi pendapatan kupon dapat diindikasikan sebagai berikut:

  1. Pembayaran klien pendapatan <777777> dividen < APPLE INC-ao> -> pembayaran dividen dari laporan SPB;
  2. Pembayaran klien pendapatan <777777> dividen < MICROSOFT COM-any>
  3. Pembayaran pendapatan pelanggan 777777i (NKD 2 OFZ 24019 ) memotong pajak 0,00 rubel -> pembayaran kupon dari laporan MOEX;
  4. Pembayaran pendapatan kepada klien 777777 dividen FGC UES - pajak pemotongan XX.XX rubel -> pembayaran dividen dari laporan MOEX. dll.

Karenanya, akan sulit dilakukan tanpa ekspresi reguler, jadi kami akan menggunakannya sepenuhnya. Sisi lain dari masalah ini adalah bahwa nama perusahaan tidak selalu bertepatan dengan nama dalam portofolio atau dalam transaksi dalam tujuan pembayaran. Oleh karena itu, nama yang diterima penerbit dari tujuan pembayaran harus dikorelasikan dengan kamus. Sebagai kamus, kami akan menggunakan berbagai penawaran, karena ada daftar perusahaan terlengkap.

Fungsi get_company_from_str mengambil nama penerbit dari komentar:

Fungsi Get_company_from_str
 def get_company_from_str(comment): company_name = '' #    / flows_pattern = [ '^.+\s<(\w+)?.+->$', '^.+\s(.+)-.+$', '^.+\(\s\d?\s(.+)\).+$', '^.+\s(.+)-.+$' ] for pattern in flows_pattern: match = re.search(pattern, comment) if match: return match.group(1).upper() return company_name 

Fungsi get_company_from_briefcase mengarahkan nama perusahaan ke kamus jika menemukan kecocokan di antara perusahaan yang berpartisipasi dalam transaksi:

Fungsi Get_company_from_briefcase
 def get_company_from_briefcase(company_name): company_name_full = None value_from_dic = df_deals[df_deals['stock_name'].str.contains(company_name)] company_arr = value_from_dic['stock_name'].unique() if len(company_arr) == 1: company_name_full = company_arr[0] return company_name_full 


Dan akhirnya, fungsi terakhir mengumpulkan data pada operasi non-perdagangan adalah get_nontrade_operation :

Fungsi get_nontrade_operation
 def get_nontrade_operation(XMLdata): nontrade_money_operation = XMLdata.find(flows) if not nontrade_money_operation: return try: for child in nontrade_money_operation: comment = child.get('comment') type_oper_match = re.search('||^.+.+.+$', comment) if type_oper_match: company_name = get_company_from_str(comment) type_oper = get_type_oper(comment) dict_flows['stock_name'].append(company_name) dict_flows['account'].append(account_name) dict_flows['date_oper'].append(to_dt(child.get(operationdate)).strftime('%Y-%m-%d')) dict_flows['type_oper'].append(type_oper) dict_flows['result'].append(float(child.get('amount'))) dict_flows['currency'].append(child.get(currency_flows)) except Exception as e: print('get_nontrade_operation --> Oops! It seems we have a BUG!', e) 

Hasil pengumpulan data dari laporan adalah tiga DataFrames, yang kira-kira sebagai berikut:

  1. DataFrame dengan informasi harga rata-rata posisi terbuka:
  2. Menangani DataFrame:
  3. DataFrame dengan informasi tentang operasi non-perdagangan:


Jadi, yang harus kita lakukan adalah melakukan penyatuan eksternal dari tabel transaksi dengan tabel informasi portofolio:

 df_result = pd.merge(df_deals, df_stocks_avg, how='outer', on=['stock_name', 'account', 'currency']).fillna(0) df_result.sample(10) 


Dan akhirnya, bagian terakhir dari pemrosesan array data adalah penggabungan array data yang diperoleh pada langkah sebelumnya dengan DataFrame untuk transaksi non-perdagangan.
Hasil pekerjaan yang dilakukan adalah satu meja datar besar dengan semua informasi yang diperlukan untuk analisis:

 df_result_full = df_result.append(df_flows, ignore_index=True).fillna(0) df_result_full.sample(10).head() 


Kumpulan data yang dihasilkan (Laporan Akhir) dari DataFrame mudah diunggah ke CSV dan kemudian dapat digunakan untuk analisis terperinci dalam sistem BI apa pun.

 if not exists('OUTPUT'): makedirs('OUTPUT') report_name = 'OUTPUT\my_trader_diary.csv' df_result_full.to_csv(report_name, index = False, encoding='utf-8-sig') 


Unggah dan proses data dalam AWS


Kemajuan tidak berhenti dan sekarang layanan cloud dan model komputasi tanpa server mendapatkan popularitas besar dalam pemrosesan dan penyimpanan data. Ini sebagian besar disebabkan oleh kesederhanaan dan murahnya pendekatan ini, ketika Anda tidak perlu membeli peralatan mahal untuk membangun arsitektur sistem untuk komputasi kompleks atau memproses data besar, tetapi Anda hanya menyewa daya di cloud untuk waktu yang Anda butuhkan dan menggunakan sumber daya yang diperlukan dengan cukup cepat dengan biaya yang relatif kecil untuk biaya yang relatif kecil .

Salah satu penyedia cloud terbesar dan paling terkenal di pasar adalah Amazon. Mari kita lihat contoh lingkungan Amazon Web Services (AWS) untuk membangun sistem analitis untuk memproses data pada portofolio investasi kami.

AWS memiliki banyak pilihan alat, tetapi kami akan menggunakan yang berikut ini:

  • Amazon S3 - penyimpanan objek, yang memungkinkan Anda menyimpan informasi dalam jumlah hampir tak terbatas;
  • AWS Glue - layanan cloud ETL paling kuat yang dapat dengan sendirinya menentukan struktur dan menghasilkan kode ETL dari data sumber yang diberikan;
  • Amazon Athena , layanan query SQL online tanpa server, memungkinkan Anda untuk dengan cepat menganalisis data dari S3 tanpa banyak persiapan. Dia juga memiliki akses ke metadata yang dipersiapkan AWS Glue, yang memungkinkan Anda untuk mengakses data segera setelah melewati ETL;
  • Amazon QuickSight - BI-service serverless , Anda dapat membangun visualisasi, laporan analitis "on the fly", dll.

Dokumentasi Amazon baik-baik saja, khususnya, ada artikel bagus Praktik Terbaik Saat Menggunakan Athena dengan AWS Glue , yang menjelaskan cara membuat dan menggunakan tabel dan data menggunakan AWS Glue. Mari kita manfaatkan ide-ide utama artikel ini dan menerapkannya untuk membuat arsitektur kita sendiri dari sistem pelaporan analitis.

File CSV yang disiapkan oleh pengurai laporan kami akan ditambahkan ke bucket S3. Direncanakan bahwa folder yang sesuai pada S3 akan diisi ulang setiap hari Sabtu - pada akhir minggu perdagangan, sehingga Anda tidak dapat melakukannya tanpa partisi data berdasarkan tanggal pembentukan dan pemrosesan laporan.
Selain mengoptimalkan operasi kueri SQL ke data tersebut, pendekatan ini akan memungkinkan kami untuk melakukan analisis tambahan, misalnya, untuk mendapatkan dinamika perubahan dalam hasil keuangan untuk setiap makalah, dll.

Bekerja dengan Amazon S3
  • Buat ember di S3, sebut saja "report-parser";
  • Dalam ember ini "report-parser" membuat folder bernama "my_trader_diary";
  • Dalam direktori "my_trader_diary" buat direktori dengan tanggal laporan saat ini, misalnya, "date_report = 2018-10-01" dan tempatkan file CSV di dalamnya;
  • Hanya demi percobaan dan pemahaman partisi yang lebih baik, kami akan membuat dua direktori lagi: "date_report = 2018-09-27" dan "date_report = 2018-10-08". Kami memasukkan file CSV yang sama di dalamnya;
  • "S3-parser" bucket S3 terakhir harus seperti yang ditunjukkan pada gambar di bawah ini:


Bekerja dengan Lem AWS
Pada umumnya, Anda hanya dapat melakukan Amazon Athena untuk membuat tabel eksternal dari data yang ada pada S3, tetapi AWS Glue adalah alat yang lebih fleksibel dan nyaman untuk ini.

  • Kami masuk ke AWS Glue dan membuat Crawler baru, yang akan mengumpulkan satu tabel dari file CSV terpisah dengan melaporkan tanggal:
    • Tetapkan nama Crawler baru;
    • Kami menunjukkan repositori dari mana mendapatkan data (s3: // report-parser / my_trader_diary /)
    • Kami memilih atau membuat peran IAM baru yang akan memiliki akses untuk meluncurkan Crawler dan akses ke sumber daya yang ditentukan pada S3;
    • Selanjutnya, Anda perlu mengatur frekuensi mulai. Kami menetapkan permintaan untuk saat ini, tetapi di masa depan, saya pikir ini akan berubah dan peluncuran akan menjadi mingguan;
    • Simpan dan tunggu Crawler dibuat.
  • Ketika Perayap memasuki status Siap, mulai saja!

  • Setelah berfungsi, tabel my_trader_diary baru akan muncul di AWS Glue: Database -> tab Tables:


Pertimbangkan tabel yang dihasilkan secara lebih detail.
Jika Anda mengklik nama tabel yang dibuat, maka kami akan pergi ke halaman dengan deskripsi metadata. Di bagian bawah ada tata letak tabel dan yang terbaru adalah kolom yang tidak ada dalam file CSV sumber - date_report. Kolom ini dibuat oleh AWS Glue secara otomatis berdasarkan definisi bagian dari sumber data (dalam Bucket S3, kami secara khusus menamai folder date_report = YYYY-MM-DD, yang memungkinkan kami untuk menggunakannya sebagai bagian yang dipisahkan oleh tanggal).

Partisi tabel

Pada halaman yang sama di sudut kanan atas terdapat tombol Lihat partisi, dengan mengklik di mana kita dapat melihat bagian mana yang dihasilkan tabel kita terdiri dari:

Analisis data


Setelah kami mengunggah data yang diunggah, kami dapat dengan mudah mulai menganalisisnya. Untuk memulai, pertimbangkan kemampuan Amazon Athena sebagai cara termudah dan tercepat untuk melakukan kueri analitik. Untuk melakukan ini, pergi ke layanan Amazon Athena, pilih database yang kami butuhkan (finansial) dan tulis kode SQL berikut:

 select d.date_report, d.account, d.stock_name, d.currency, sum(d.quantity) as quantity, round(sum(d.result), 2) as result from my_trader_diary d group by d.date_report, d.account, d.stock_name, d.currency order by d.account, d.stock_name, d.date_report; 

Permintaan ini akan menampilkan kepada kami hasil keuangan bersih untuk setiap keamanan untuk semua tanggal pelaporan. Karena kami mengunduh laporan yang sama tiga kali untuk tanggal yang berbeda, hasilnya tidak akan berubah, yang, tentu saja, di pasar nyata akan berbeda:


Tetapi bagaimana jika kita ingin memvisualisasikan data yang diterima dalam bentuk tabel atau diagram yang fleksibel? Di sini Amazon QuickSight datang untuk menyelamatkan, dengan bantuan yang Anda dapat mengkonfigurasi analisis fleksibel hampir secepat menulis query SQL. Kami akan pergi ke layanan Amazon QuickSight (jika Anda belum mendaftar di sana, maka pendaftaran diperlukan).

Klik pada tombol Analisis baru -> Dataset baru dan di jendela yang muncul pilih sumber untuk dataset, klik pada Athena:



Kami akan datang dengan nama untuk sumber data kami, misalnya, "PNL_analisis" dan klik tombol "Buat sumber data".

Selanjutnya, jendela Choose your table open, di mana Anda perlu memilih database dan tabel sumber data. Kami memilih database - keuangan, dan tabel di dalamnya: my_traider_diary. Secara default, seluruh tabel digunakan, tetapi jika Anda memilih "Gunakan SQL kustom", Anda dapat menyesuaikan dan menyempurnakan sampel data yang Anda butuhkan. Sebagai contoh, kami menggunakan seluruh tabel dan klik tombol Edit / Pratinjau Data.

Halaman baru akan terbuka di mana Anda dapat membuat pengaturan tambahan dan memproses data yang ada.

Sekarang kita perlu menambahkan bidang terhitung tambahan ke dataset kami: kuartal dan tahun operasi. Pembaca yang penuh perhatian mungkin memperhatikan bahwa manipulasi seperti itu lebih mudah dilakukan di sisi parser sebelum menyimpan Laporan Akhir ke CSV. Tidak diragukan lagi, tujuan saya sekarang adalah untuk menunjukkan kemampuan dan fleksibilitas pengaturan sistem BI dengan cepat. Kami terus membuat bidang terhitung dengan mengklik tombol "Bidang baru".

Buat bidang baru

Untuk menyoroti tahun operasi dan kuartal, rumus sederhana digunakan:


Mengisi rumus untuk bidang baru

Ketika bidang terhitung telah berhasil dibuat dan ditambahkan ke pilihan, berikan nama ke dataset kami, misalnya, "my_pnl_analyze" dan klik tombol "Simpan dan visualisasikan".

Setelah itu, kami mentransfer ke papan utama Amazon QuickSight dan hal pertama yang perlu kami lakukan adalah menyiapkan filter untuk tanggal laporan (dengan mempertimbangkan bahwa data yang sama dikumpulkan dari tiga bagian). Pilih tanggal pelaporan 2018-10-01 dan klik tombol Terapkan dan buka tab Visualisasikan.

Pengaturan filter

Sekarang kita dapat memvisualisasikan hasil portofolio di pesawat apa pun, misalnya, untuk setiap keamanan di dalam akun perdagangan, dan dibagi pada gilirannya dengan mata uang (karena hasilnya tidak sebanding dalam mata uang yang berbeda) dan jenis operasi. Mari kita mulai dengan alat paling kuat dari BI - tabel pivot. Untuk menghemat ruang dan menampilkan fleksibilitas, saya meletakkan mata uang dalam kontrol terpisah (analog slice di MS Excel)

Tabel di atas menunjukkan bahwa jika seorang investor memutuskan untuk menjual semua saham FGC UES sekarang, ia dengan demikian akan mencatat kerugian, seperti Dividen dibayarkan dalam jumlah 1.509,91 p. mereka tidak menanggung biayanya (1.763,36 rubel - perbedaan nilai tukar negatif dan 174 rubel - pajak penghasilan pribadi atas dividen). Masuk akal untuk menunggu dan menunggu waktu yang lebih baik di Exchange.

Grafik berikut adalah bagan batang:


Dan sekarang kita akan membentuk tabel yang akan menunjukkan kepada kita berapa banyak kita berinvestasi di masing-masing kertas, berapa hari itu dalam portofolio kita dan berapa profitabilitas untuk seluruh periode kepemilikan. Untuk melakukan ini, tambahkan dua bidang terhitung baru: sum_investment dan count_days.

Jumlah sum_investment
sum_investment ( ) :

ifelse({stock_name} = ' 24019',{avg_open_price} * quantity * 10,{avg_open_price} * quantity)

, – ( – 1000).

Bidang count_days
count_day ( ) :

dateDiff(parseDate({date_oper}),parseDate({date_report}))

Tabel final disajikan pada tangkapan layar di bawah ini:



Kesimpulan dan Ringkasan


Kami telah memeriksa dengan Anda implementasi parser laporan dan metode untuk menganalisis data yang disiapkan olehnya β€œon the fly” menggunakan layanan Amazon. Kami juga menyentuh beberapa aspek bisnis dan fundamental dari analisis portofolio investasi, seperti topik ini hampir sangat besar dan agak sulit untuk memasangnya dalam satu artikel, saya pikir masuk akal untuk meletakkannya di publikasi terpisah atau bahkan serangkaian publikasi.

Adapun penggunaan alat pemrosesan pelaporan broker dan pendekatan serta algoritma yang terlibat di dalamnya, mereka dapat digunakan (dengan modifikasi yang sesuai) untuk memproses pelaporan broker lain. Bagaimanapun, jika Anda berencana untuk menyesuaikan kode dengan kebutuhan Anda, saya siap memberikan beberapa tips, jadi jangan ragu untuk bertanya - saya pasti akan mencoba menjawabnya.

Saya yakin bahwa sistem ini akan menemukan aplikasinya dan akan memiliki pengembangan lebih lanjut. Misalnya, direncanakan untuk menambah perhitungan PNL lengkap untuk portofolio, akuntansi penyimpanan dan biaya lainnya (misalnya, untuk menarik dana), serta membayar obligasi, dll. ... Bidang yang dihitung pada sisi Quicksight digunakan untuk tujuan demonstrasi, dalam versi pengurai berikutnya, semua kolom tambahan ini akan porting ke Python dan akan dihitung pada sisi parser.

Sebagai seorang arsitek dan pelanggan bisnis utama dari solusi ini, saya melihat peningkatan lebih lanjut sebagai berikut: well, saya tidak ingin secara manual meminta laporan XML ini setiap waktu! Tentu saja, tidak ada kemungkinan lain sejauh ini, tetapi API Broker dengan transfer token dan rentang pengambilan sampel akan ideal untuk menerima pelaporan mentah mingguan. Pemrosesan otomatis penuh selanjutnya di sisi Amazon: mulai dari memicu pekerjaan ETL pada AWS Glue hingga mendapatkan hasil yang sudah jadi dalam bentuk grafik dan tabel di Amazon QuickSight akan memungkinkan Anda untuk mengotomatiskan proses sepenuhnya.

Kode sumber lengkap dapat ditemukan di repositori GitHub saya

Source: https://habr.com/ru/post/id426027/


All Articles