Bagaimana cara berlangganan acara .NET di pendengar python menggunakan pythonnet?

Nov 15 2020

Saya mencoba membuat pendengar acara berlangganan acara tick (harga) dari aplikasi perdagangan FX, menggunakan Python. Aplikasi aslinya adalah aplikasi Windows 32-bit asli yang disebut MetaTrader4 . Ini tidak memiliki API apa pun, jadi jembatan mtapi telah dirancang dalam .NET untuk memungkinkan bahasa pemrograman lain berinteraksi dengannya. Aplikasi memiliki beberapa peristiwa yang ditentukan, dua di antaranya adalah: QuoteUpdatedan QuoteUpdated.

Jadi saya ingin menulis pendengar ( delegasi ?) Menggunakan python.net untuk berlangganan acara ini. Tetapi karena saya tidak dapat memahami bagaimana kode .NET menghasilkan peristiwa ini, dan juga cara menggunakan pythonnet dengan benar , saya belum bisa membuatnya berfungsi. Saya juga terus mengalami kesalahan:

TypeError: 'EventBinding' object is not callable

Googling ini tidak kembali sesuatu yang berguna, selain ini "FIXME" komentar.

Ini kode saya:

import os, sys, clr
sys.path.append(r"C:\Program Files\MtApi")
asm = clr.AddReference('MtApi')
import MtApi as mt

res = 0

def printTick(symbol, ask, bid):
    print('Tick: Symbol: {}  Ask: {:.5f}  Bid: {:.5f}'.format(symbol, ask, bid))

# Setup .NET API bridge connection
mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222);

#--------------------------------------
# Register and use the listener
#--------------------------------------
# This does NOT work!
mtc.QuoteUpdate += printTick

#...

Maksud dari kode saya harus jelas.

T: Bagaimana cara membuat pendengar saya bersemangat saat menerima QuoteUpdateacara .NET?


Sebagai referensi:

  • Kode .NET di C # (dari MtApiClient.cs terlihat seperti ini:
...
private void _client_QuoteUpdated(MTApiService.MtQuote quote) { 
    if (quote != null) { 
        QuoteUpdate?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote))); 
        QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask); 
    } 
} 
...
public event MtApiQuoteHandler QuoteUpdated; 
public event EventHandler<MtQuoteEventArgs> QuoteUpdate; 
public event EventHandler<MtQuoteEventArgs> QuoteAdded; 
public event EventHandler<MtQuoteEventArgs> QuoteRemoved; 
  • Dan aplikasi VB Test kecil terlihat seperti ini:
Imports MtApi
Public Class Form1
    Private apiClient As MtApiClient
    Public Sub New()
        InitializeComponent()
        apiClient = New MtApiClient
        AddHandler apiClient.QuoteUpdated, AddressOf QuoteUpdatedHandler
    End Sub

    Sub QuoteUpdatedHandler(sender As Object, symbol As String, bid As Double, ask As Double)
        Dim quoteSrt As String
        quoteSrt = symbol + ": Bid = " + bid.ToString() + "; Ask = " + ask.ToString()
        ListBoxQuotesUpdate.Invoke(Sub()
                                       ListBoxQuotesUpdate.Items.Add(quoteSrt)
                                   End Sub)
        Console.WriteLine(quoteSrt)
    End Sub
    Private Sub btnConnect_Click(sender As System.Object, e As System.EventArgs) Handles btnConnect.Click
        apiClient.BeginConnect(8222)
    End Sub
    Private Sub btnDisconnect_Click(sender As System.Object, e As System.EventArgs) Handles btnDisconnect.Click
        apiClient.BeginDisconnect()
    End Sub
End Class

MEMPERBARUI

Sebagai referensi, kami memiliki panggilan DLL yang relevan berikut, yang diberikan oleh atribut, tipe, dan __doc__:

attr: QuoteAdded             type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteRemoved           type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteUpdate            type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteUpdated           type: <class 'CLR.EventBinding'>    doc: <n/a>

attr: add_QuoteAdded         type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteRemoved       type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdate        type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdated       type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteUpdated(MtApi.MtApiQuoteHandler)

attr: remove_QuoteAdded      type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteRemoved    type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdate     type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdated    type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteUpdated(MtApi.MtApiQuoteHandler)


Masalah Serupa:

Secara harfiah ada 100-an masalah SO terkait, dan saya mungkin telah melihat lebih dari 60% di antaranya tetapi dengan hampir tidak ada keberhasilan untuk penerapan berdasarkan kasus penggunaan. Beberapa diantaranya adalah:

  • Apakah kelas Python mendukung acara seperti bahasa lain?
  • Apa cara yang benar untuk mengubah registrasi event handler ini dari C # ke VB.net?
  • Bagaimana cara mengubah delegasi VB menjadi penangan acara python?
  • https://ironpython.net/documentation/dotnet/dotnet.html (mungkin juga relevan)
  • https://openbookproject.net/thinkcs/python/english3e/events.html
  • https://code.activestate.com/recipes/410686-c-style-events-in-python/

Jawaban

3 not2qubit Nov 23 2020 at 21:56

Setelah beberapa hari dan beberapa jam saya menemukan kombinasi kesalahan. Seperti biasa, kombinasi 2-3 kesalahan sederhana bisa membuat hidup Anda sengsara untuk waktu yang lama. Tapi kesalahan terbesar dari semuanya, adalah tertipu untuk berpikir bahwa pendaftar (alias delegasi ) harus dibuat rumit dengan sekumpulan __init__dan __iadd__fungsi. Salah! Python.NET hanya berfungsi sebagian besar waktu tetapi kesalahan yang Anda dapatkan (jika ada) sangat tidak berguna jika Anda membuat kesalahan kecil.

Ada 1,5 masalah dengan kode asli saya.

  • Ada 2 fungsi Kutipan yang berbeda , yaitu:

  • QuoteUpdateyang mengembalikan pengirim dan objek bernama "MtQuoteEventArgs" di .NET

  • QuoteUpdatedyang mengembalikan pengirim dan 3 argumen .

  • Oleh karena itu kita perlu memperbaiki fungsi printTick () dan baris listener.

Kode yang dikoreksi adalah:

def printTick(source, symbol, ask, bid):
    print('Tick: Symbol: {}  Ask: {:.5f}  Bid: {:.5f}'.format(symbol, ask, bid))

...

mtc.QuoteUpdates += printTick

Untuk info tambahan tentang acara & delegasi C # :

  • https://www.tutorialsteacher.com/csharp/csharp-event
1 LOST Nov 20 2020 at 05:24

Menurut dokumentasi mtapi yang Anda tautkan, kodenya harus:

def printTick(sender, args):
  print(str(args.Quote.Instrument))


mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222)

mtc.QuoteUpdate += printTick  # Subscribe & handle new repeated events

rA  = mtc.SymbolInfoTick(SYM) # Make a request to get a one-time tick data

# Need wait loop here