Let me try to define the problem with a question: how to mutate variables defined in an outer scope inside an inner function?
Let’s illustrate with an example: cumulative moving averages of real-time price points .
In PyQuantLET we define a simple model to read ticks from an inbound endpoint, generate a cumulative moving average, and forward the result to an outbound endpoint in two lines:
f = quantlet.handler.stat.cma() [outbound((x, f(x))) for x in inbound]
Concrete inbound and outbound endpoints are defined as part of the execution mode of this model. A mode of execution could be a simulation in which the inbound endpoint is a real-time feed for trades of a specific underlying, and an outbound plot of price points and cumulative moving average.
execute_mode(id='simulation', model=cma(inbound=feed(''tcp://localhost:61616?wireFormat=openwire'), outbound=graph(['plot'] ) )
Of course, nothing realistic, but that’s all it takes. Ok, let’s now define the function for cumulative moving average (in reality we would use classes for the same purpose, but let’s stick to this for now):
def cma(): // this is wrong total, counter = (0,0) def result(value): total = total + value counter = counter + 1 return total / counter return result
If you try this version, you will get something like this:
UnboundLocalError: local variable 'total' referenced before assignment
The message is self explanatory – seems like the reason is that rebinding names in a closed scope is not allowed in Python. Nothing like a dictatorship for life…
So, now the good part – the solution – rewrite your function so variables in the outer scope are associated to a container object, see…
def cma(): total, counter =([0],[0]) def result(value): total[0] = total[0] + value counter[0] = counter[0] + 1 return total[0] / counter[0] return result
Looks weird, but works – you can try yourself
This is pretty technical.
Thanks for sharing this!