How to change string into a QuickFix message? - python

I am trying to read my FIX logs and to parse them with the cracker that I wrote in python. However, this does not work because in my cracker I have calls like message.getHeader() which are QuickFix methods. They unsurprisingly return an error:
AttributeError: 'str' object has no attribute 'getHeader'
The logs are all strings, but the cracker is embedded within QuickFix and so uses QF methods. Is there any way to take the string and transform it into a QF message so I can just call crack(message) on it, or do I have to rewrite my cracker for this special case?

The following code should work.
import quickfix as qfix
import quickfix44 as q44
message = q44.ExecutionReport()
message.setString(input_string, True, qfix.DataDictionary('CustomDictionary.xml'))
'message' object will be updated in place and you should be able to use it as a quickfix Message object

The way that I do it in C# is to read tag 35 to see what message type I need to create. Then, I create that message type, and use the setString method to populate it. Something like this:
if (line.Contains("35=8"))
{
message = new QuickFix44.ExecutionReport();
}
else if(line.Contains("35=AS"))
{
message = new QuickFix44.AllocationReport();
}
. . . . and so on
message.setString(line, true, dictionary);
application.fromApp(message, sessionId); //The cracker takes care of it from here
where dictionary is my data dictionary. Is a similar method available in the Python bindings?

The following also works and doesn't require prior knowledge of message type.
import quickfix as fix
string = "8=FIX.4.49=24735=s34=549=sender52=20060319-09:08:20.88156=target22=840=244=948=ABC55=ABC60=20060319-09:08:19548=184214549=2550=0552=254=1453=2448=8447=D452=4448=AAA35777447=D452=338=954=2453=2448=8447=D452=4448=aaa447=D452=338=910=056"
data_dictionary = fix.DataDictionary("FIX44.xml")
message = fix.Message(string, data_dictionary, True)
print(message.toXML())

Related

Create A FIX Message using Quickfix Python

I am a very new user to Quickfix Python. I want to send a QuoteRequest. My function to create a new quote request message is as below:
import quickfix as fix
def create_quote_request():
message = fix.Message()
header = message.getHeader()
header.setField(fix.MsgType(fix.MsgType_QuoteRequest))
gp = fix.Group()
gp.setField(fix.Symbol("GBPUSD"))
gp.setField(fix.Side(fix.Side_BUY))
gp.setField(fix.Account("TestAcc"))
gp.setField(fix.Currency("GBP"))
message.addGroup(gp)
fix.Session.sendToTarget(message, self.sessionID)
When I execute the code, I am getting error as below:
NotImplementedError: Wrong number r type of arguments for overloaded function 'new_group'.
Possible C/C++ prototypes are:
FIX::Group::Group(int, int)
FIX::Group::Group(int, int, int const[])
FIX::Group::Group(int, int, message_order const &)
FIX::Group::Group(FIX::Group const &)
I did read the documentation and found that the Group object requires arguments
Group(int field, int delim)
Not sure what to pass the values for field and delim. Appreciate your response and help.
not sure I´m on time to help. But I will try. I think #JimmyNJ is giving you proper answer.
According to official doc you can easily do it, but you don´t have to use a generic group, you have to use specific group available to your kind of message.
As far as I know, you should program something like this.
from quickfix44 import QuoteRequest
import quickfix as fix
message = QuoteRequest()
group = QuoteRequest.NoRelatedSym()
group.setField(fix.Symbol("GBPUSD"))
group.setField(fix.Side(fix.Side_BUY))
group.setField(fix.Account("TestAcc"))
group.setField(fix.Currency("GBP"))
message.addGroup(group)
I´m assuming you want to add these 4 tags into NoRelatedSym group, based in their tag numbers. I´ve also used FIX 44 version, maybe you are using a different version, but main idea is the same.

IronPython: script validation via C# code

I'm working with IronPython in a C#/.Net Core 3.1 project and I need to be able to validate a script before executing it in a production environment.
I have found this solution, creating my custom Microsoft.Scripting.Hosting.ErrorListener implementation:
public class IronPythonListener : ErrorListener
{
public List<ValidationError> Errors = new List<ValidationError>();
public override void ErrorReported(ScriptSource source, string message, SourceSpan span, int errorCode, Severity severity)
{
Errors.Add(new ValidationError
{
Message = message,
ErrorCode = errorCode,
Severity = severity,
Span = span
});
}
}
and then passing an instance of it to the Microsoft.Scripting.Hosting.ScriptSource.Compile(ErrorListener) method:
IronPythonListener listener = new IronPythonListener();
ScriptEngine engine = Python.CreateEngine();
ScriptSource scriptSource = engine.CreateScriptSourceFromString(script, SourceCodeKind.AutoDetect);
CompiledCode code = scriptSource.Compile(listener);
In listener.Errors list I find all the compilation errors.
This solution works, but for my purposes it is not complete, because for example:
if the passed script is something like my_var = 5 + "some text", listener.Errors is empty and the script is considered valid even though it cannot be executed (in fact, it throws a unsupported operand type(s) for +: 'int' and 'str' exception)
if the passed script contains calls to undefined functions (e.g. length(my_string) instead of len(my_string)), it is considered valid
Another thing that seems strange to me is that all the errors I can find are of type Severity.FatalError (e.g. passing my_var = 6 +), but I'm not able to find any Severity.Error or Severity.Warning.
Is there a way to improve the validation, without executing my compiled script?
Thanks in advance for any help, unfortunately I cannot find so much documentation about this.
Edit: I found some online validators (e.g. https://repl.it/languages/python3 or http://pep8online.com/) and they also don't provide a complete python validation (in the former one, validation is handled better by the IDE, but the 5 + "some text" error is detected only at execution time). Of course I can try to execute the script and catch the exception when listener.Errors is empty, but it would be better to avoid this.
Edit 2: I tried also this solution, using a separated python script to validate mine, but I have the same issues with undefined functions and wrong operators usage.

Why is format(str(var)) giving me an Attribute Error for my os.system

I'm trying to make a Python script that connects me to a VPN Server 'number' (with this number as a variable)
I wrote:
import os
VPNServer = 0
VPNServer += 1
os.system("networksetup -connectpppoeservice 'VPNServer {servernumber}'").format(servernumber = str(VPNServer))
print("→ Successfully connected to", "VPNServer", VPNServer)
But everytime I try to run it, the console gives me an AttributeError
AttributeError: 'int' object has no attribute 'format'
I don't understand it because I took the string version of the variable
If someone could help, it would be super cool
I'm on macOS and I'm using Python 3.8.1
In the snippet you provided, you write
os.system('<some string>').format(args)
You are making the format call on the return value of os.system, which happens to be an integer. This is identical to writing e.g.
5.format(args)
Since int objects have no attribute format, you get the AttributeError you described.
What you want to write is
os.system('<some string>'.format(args))
In this specific case, your snippet should resemble
os.system(
"networksetup -connectpppoeservice 'VPNServer {servernumber}'"
.format(servernumber=VPNServer)
)
Note that the str(VPNServer) call is superfluous, since format will autmatically call the __str__ method of the object provided.

Error when changing instance type in a python for loop

I have a Python 2 script which uses boto3 library.
Basically, I have a list of instance ids and I need to iterate over it changing the type of each instance from c4.xlarge to t2.micro.
In order to accomplish that task, I'm calling the modify_instance_attribute method.
I don't know why, but my script hangs with the following error message:
EBS-optimized instances are not supported for your requested configuration.
Here is my general scenario:
Say I have a piece of code like this one below:
def change_instance_type(instance_id):
client = boto3.client('ec2')
response = client.modify_instance_attribute(
InstanceId=instance_id,
InstanceType={
'Value': 't2.micro'
}
)
So, If I execute it like this:
change_instance_type('id-929102')
everything works with no problem at all.
However, strange enough, if I execute it in a for loop like the following
instances_list = ['id-929102']
for instance_id in instances_list:
change_instance_type(instance_id)
I get the error message above (i.e., EBS-optimized instances are not supported for your requested configuration) and my script dies.
Any idea why this happens?
When I look at EBS optimized instances I don't see that T2 micros are supported:
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html
I think you would need to add EbsOptimized=false as well.

pyvmomi:error when calling RelocateVM

Hi I am using pyvmomi API, to perform vmotions against a cluster when DRS is set to manual mode. I am going through a vcenter and querying a cluster and getting recommendation and using that to perform the Vmotions. The code is something like this.
content=getVCContent(thisHost, {'user':username,'pwd':decoded_password},logger)
allClusterObj = content.viewManager.CreateContainerView(content.rootFolder, [pyVmomi.vim.ClusterComputeResource], True)
allCluster = allClusterObj.view
for thisDrsRecommendation in thisCluster.drsRecommendation:
print thisDrsRecommendation.reason
for thisMigration in thisDrsRecommendation.migrationList:
print ' vm:', thisMigration.vm.name
while True:
relocate_vm_to_host(thisMigration.vm.name,thisMigration.destination.name, allClusterObj.view)
#FUNCTION definition
def relocate_vm_to_host(vm, host , allCluster):
for thisCluster in allCluster:
for thisHost in thisCluster.host:
if thisHost.name == host:
for thisVm in thisHost.vm:
print 'Relocating vm:%s to host:%s on cluster:%s' %(thisVm.name,thisHost.name,thisCluster.name)
task = thisVm.RelocateVM(priority='defaultpriority')
I am getting an error saying the attribute doesn't exist.
AttributeError: 'vim.VirtualMachine' object has no attribute 'RelocateVM'
But the pyvmomi documentaion here https://github.com/vmware/pyvmomi/blob/master/docs/vim/VirtualMachine.rst
has a detailed explanation for the method
RelocateVM(spec, priority):
Anyone know what's the reason the method is missing? I also tried checking the available methods of the object ,that has RelocateVM_Task ,instead of RelocateVM(for which I couldn't find documentation) When I used that I get this error
TypeError: For "spec" expected type vim.vm.RelocateSpec, but got str
I checked the documentation for vim.vm.RelocateSpec, I am calling it in a function , but still throws an error.
def relocate_vm(VmToRelocate,destination_host,content):
allvmObj = content.viewManager.CreateContainerView(content.rootFolder, [pyVmomi.vim.VirtualMachine], True)
allvms = allvmObj.view
for vm in allvms:
if vm.name == VmToRelocate:
print 'vm:%s to relocate %s' %(vm.name , VmToRelocate)
task = vm.RelocateVM_Task(spec = destination_host)
Any help is appreciated.
Thanks
Looks like a mistake in the documentation. The method is called Relocate (and not RelocateVM).
Note, BTW, that in your first sample you're not passing the destination host to the call to Relocate so something is definitely missing there.
You can see some samples at https://gist.github.com/rgerganov/12fdd2ded8d80f36230f or at https://github.com/sijis/pyvmomi-examples/blob/master/migrate-vm.py.
Lastly, one way to realize you're using the wrong name is by calling Python's dir method on a VirtualMachine object. This will list all properties of the object so you can see which methods it has:
>>> vm = vim.VirtualMachine('vm-1234', None)
>>> dir(vm)
['AcquireMksTicket', [...] 'Relocate', 'RelocateVM_Task', [...] ]
(abbreviated output)

Categories

Resources