วิธีสมัครรับเหตุการณ์. NET ใน python listener โดยใช้ pythonnet

Nov 15 2020

ฉันกำลังพยายามทำให้ผู้ฟังเหตุการณ์สมัครเป็นสมาชิกเหตุการณ์เห็บ (ราคา) จากแอปพลิเคชันการซื้อขาย FX โดยใช้ Python แอพลิเคชันเดิมเป็น 32 บิตของ Windows แอพพลิเคพื้นเมืองที่เรียกว่าโปรแกรม MetaTrader4 สิ่งนี้ไม่มี API ใด ๆ ดังนั้นmtapi bridge จึงได้รับการออกแบบใน. NET เพื่อให้ภาษาโปรแกรมอื่น ๆ สามารถโต้ตอบกับมันได้ แอปพลิเคชันมีการกำหนดเหตุการณ์บางอย่างซึ่งสองเหตุการณ์คือ: QuoteUpdateและQuoteUpdated.

ดังนั้นฉันจึงต้องการเขียนผู้ฟัง ( delegate ?) โดยใช้python.netเพื่อสมัครเข้าร่วมกิจกรรมนี้ แต่เนื่องจากฉันไม่สามารถเข้าใจว่าโค้ด. NET สร้างเหตุการณ์เหล่านี้ได้อย่างไรและไม่สามารถใช้pythonnetอย่างถูกต้องได้อย่างไรฉันจึงไม่สามารถทำให้สิ่งนี้ทำงานได้ ฉันยังคงพบข้อผิดพลาด:

TypeError: 'EventBinding' object is not callable

Googling นี้ไม่ได้กลับมาอะไรที่เป็นประโยชน์นอกเหนือนี้ "FIXME" ความคิดเห็น

นี่คือรหัสของฉัน:

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

#...

ความตั้งใจสำหรับรหัสของฉันควรชัดเจน

ถาม: ฉันจะทำให้ผู้ฟังของฉันลุกเป็นไฟได้อย่างไรเมื่อได้รับQuoteUpdateเหตุการณ์. NET


สำหรับการอ้างอิง:

  • รหัส. NET ใน C # (จากMtApiClient.csมีลักษณะดังนี้:
...
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; 
  • และแอป VB Testขนาดเล็กมีลักษณะดังนี้:
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

อัปเดต

สำหรับการอ้างอิงเรามีการเรียก DLL ที่เกี่ยวข้องดังต่อไปนี้ซึ่งกำหนดโดยแอตทริบิวต์ประเภทและ__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)


ปัญหาที่คล้ายกัน:

มีปัญหา SO ที่เกี่ยวข้องอย่างแท้จริง 100 รายการและฉันอาจดูมากกว่า 60% ของปัญหาเหล่านี้ แต่แทบจะไม่มีความสำเร็จในการบังคับใช้ตามกรณีการใช้ บางส่วน ได้แก่ :

  • คลาส Python รองรับเหตุการณ์เหมือนภาษาอื่น ๆ หรือไม่?
  • วิธีใดที่ถูกต้องในการแปลงการลงทะเบียนตัวจัดการเหตุการณ์นี้จาก C # เป็น VB.net
  • ฉันจะแปลงตัวแทน VB เป็นตัวจัดการเหตุการณ์ python ได้อย่างไร
  • https://ironpython.net/documentation/dotnet/dotnet.html (อาจเกี่ยวข้องด้วย)
  • https://openbookproject.net/thinkcs/python/english3e/events.html
  • https://code.activestate.com/recipes/410686-c-style-events-in-python/

คำตอบ

3 not2qubit Nov 23 2020 at 21:56

หลังจากนั้นไม่กี่วันและหลายชั่วโมงฉันพบว่ามีข้อผิดพลาดหลายอย่าง เช่นเคยการรวมกันของข้อผิดพลาด 2-3 ข้ออาจทำให้ชีวิตของคุณเป็นทุกข์ไปอีกนาน แต่ความผิดพลาดที่ยิ่งใหญ่ที่สุดของทั้งหมดคือการถูกหลอกให้คิดว่า listner (aka. delegate ) ต้องซับซ้อนกับกลุ่ม__init__และ__iadd__ฟังก์ชันมากมาย ไม่ถูกต้อง! Python.NET ใช้งานได้เกือบตลอดเวลา แต่ข้อผิดพลาดที่คุณได้รับ (ถ้ามี) นั้นค่อนข้างไร้ประโยชน์หากคุณทำผิดพลาดเล็กน้อย

มีปัญหา 1.5 กับรหัสเดิมของฉัน

  • มีฟังก์ชั่นใบเสนอราคา 2 แบบ ได้แก่ :

  • QuoteUpdateซึ่งส่งคืนผู้ส่งและวัตถุชื่อ "MtQuoteEventArgs" ใน. NET

  • QuoteUpdatedซึ่งผลตอบแทนที่ผู้ส่งและ 3 ข้อโต้แย้ง

  • ดังนั้นเราต้องแก้ไขทั้งฟังก์ชัน printTick ()และฟังก์ชั่น

รหัสที่แก้ไขคือ:

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

...

mtc.QuoteUpdates += printTick

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์ C # และผู้ได้รับมอบหมาย :

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

ตามเอกสาร mtapi ที่คุณเชื่อมโยงรหัสควรเป็น:

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