<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pt-BR">
	<id>http://fiscomp.if.ufrgs.br/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bleo</id>
	<title>Física Computacional - Contribuições do usuário [pt-br]</title>
	<link rel="self" type="application/atom+xml" href="http://fiscomp.if.ufrgs.br/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bleo"/>
	<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php/Especial:Contribui%C3%A7%C3%B5es/Bleo"/>
	<updated>2026-04-19T18:52:44Z</updated>
	<subtitle>Contribuições do usuário</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5331</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5331"/>
		<updated>2021-05-26T23:24:45Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações e o Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;Modelo de Ising[https://en.wikipedia.org/wiki/Ising_model]&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas visões em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo. A temperatura no caso deste modelo, vai ditar a distribuição de estratégias: para uma temperatura baixa, as estratégias associadas ao spin up dominarão; já para uma temperatura mais elevada, as estratégias associadas ao spin down predominarão.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5330</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5330"/>
		<updated>2021-05-26T23:21:03Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;Modelo de Ising[https://en.wikipedia.org/wiki/Ising_model]&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo. A temperatura no caso deste modelo, vai ditar a distribuição de estratégias: para uma temperatura baixa, as estratégias associadas ao spin up dominarão; já para uma temperatura mais elevada, as estratégias associadas ao spin down predominarão.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5329</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5329"/>
		<updated>2021-05-26T23:20:46Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;(Modelo de Ising)[https://en.wikipedia.org/wiki/Ising_model]&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo. A temperatura no caso deste modelo, vai ditar a distribuição de estratégias: para uma temperatura baixa, as estratégias associadas ao spin up dominarão; já para uma temperatura mais elevada, as estratégias associadas ao spin down predominarão.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5328</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5328"/>
		<updated>2021-05-26T23:17:54Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;Modelo de Ising[https://en.wikipedia.org/wiki/Ising_model]&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo. A temperatura no caso deste modelo, vai ditar a distribuição de estratégias: para uma temperatura baixa, as estratégias associadas ao spin up dominarão; já para uma temperatura mais elevada, as estratégias associadas ao spin down predominarão.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5326</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5326"/>
		<updated>2021-05-26T23:11:33Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Discussão */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
N indica o limite do eixo x. Quanto maior o seu valor, mais demorada fica a simulação. Porém, valores pequenos de N podem gerar resultados inconclusivos.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta x = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica a unidade infinitesimal do eixo x (neste caso, o único eixo do problema).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta t = 0.3 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica quanto tempo cada passo da simulação percorre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de renda.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de densidade populacional.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é um parâmetro intimamente ligado com o movimento da população para regiões com alta concentração de dinheiro. Nas palavras de Sayama,&amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt; indica a &amp;quot;habilidade que as pessoas da rede tem de 'sentir o cheiro' do dinheiro&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é utilizado no cálculo de &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, como descrito acima, seguindo a fórmula &amp;lt;math&amp;gt;v = \alpha \Delta t&amp;lt;/math&amp;gt;. Está relacionado com a velocidade do progresso da economia, ou seja, quão rápido cresce a renda em uma posição da malha através da influência da população. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é utilizado na fórmula &amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;, que indica a taxa de decaimento da renda em regiões da malha com baixa população.&lt;br /&gt;
&lt;br /&gt;
Estes parâmetros foram utilizados pois representam bem a característica do sistema de Keller-Segel que queremos representar: a formação de clusters de população na malha &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;. Uma nova combinação de parâmetros poderia resultar em resultados diferentes, mas que fogem do escopo deste projeto.&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; \mathcal{C}_1 = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; \mathcal{C}_2 = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida reduzida, pois o dinheiro decai a uma taxa &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt;, como já falado. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a taxa de evolução do sistema monetário em pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior largura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta condição inicial da população se assemelha muito à proposição inicial que Keller e Segel fizeram para um sistema celular, como descrito acima. Temos uma concentração homogênea de &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com formato gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de formato gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível mais uma vez a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema entre em um estado com somente um pico de formato gaussiano na população, e um pico na renda, com largura maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.zeros((parametros.N_y, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Código completo se encontra no Github.'''''&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
Nas figuras abaixo, sendo a primeira uma figura retirada do livro do Sayama &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;, e a segunda gerada utilizando o modelo construído, a fim de comparar com a primeira, observa-se, partindo de uma população uniforme na malha e de uma renda aleatoriamente distribuída, a formação de grupos (pontos mais escuros), deste modo provando que o modelo construído chega nos mesmos resultados que a referência.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-keller-segel.png|600px|thumb|center|Fonte: Sayama]]&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-pop-renda.png|600px|thumb|center|Clusters obtidos para os casos estudados, sob condições iniciais semelhantes às aplicadas por Sayama na imagem acima. Na imagem, observa-se, assim como na referência, o principal objetivo da aplicação do modelo: a presença de clusters de população sob a malha.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os gifs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
import imageio  &amp;quot;&amp;quot;&amp;quot;Biblioteca p/ gerar os gifs. Para instalar: pip install imageio&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_gif(p,m,t,images):&lt;br /&gt;
    fig,ax = plt.subplots(1,2,figsize=(10,5))&lt;br /&gt;
&lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[0].plot(100*p,color='purple')&lt;br /&gt;
    ax[0].set_ylabel(&amp;quot;%&amp;quot;)&lt;br /&gt;
    ax[0].grid(False)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[1].plot(m,color='darkgreen')&lt;br /&gt;
    ax[1].fill_between(np.arange(m.shape[0]),m,color='green',alpha=0.5,label=&amp;quot;Total money: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax[1].set_ylabel(&amp;quot;$&amp;quot;)&lt;br /&gt;
    ax[1].grid(False)&lt;br /&gt;
    ax[1].legend()&lt;br /&gt;
    &lt;br /&gt;
    plt.tight_layout()&lt;br /&gt;
    plt.savefig(imgname) #Salva o frame do sistema&lt;br /&gt;
    plt.close()&lt;br /&gt;
    &lt;br /&gt;
    images.append(imageio.imread(imgname)) #Adiciona a imagem na lista indicada&lt;br /&gt;
    os.remove(imgname) #Remove a imagem recém criada&lt;br /&gt;
    time.sleep(0.5)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
images = [] #Vetor para alocar as imagens que formarão o gif.&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if i % 10 == 0:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_gif(p,m,t,images)&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
imageio.mimsave(&amp;quot;foo.gif&amp;quot;, images,fps=3) #Ajustar fps conforme desejar. Quanto maior, + imagens/segundo&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os snapshots do sistema ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_grid(fig,p,m,i,t,ncols,nrows=2):&lt;br /&gt;
    #Population&lt;br /&gt;
    ax_p = fig.add_subplot(nrows,ncols,i+1)&lt;br /&gt;
    ax_p.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_p.plot(100*p,color='purple')&lt;br /&gt;
    ax_p.fill_between(np.arange(N),100*p,color='purple',alpha=0.5)&lt;br /&gt;
    &lt;br /&gt;
    #Money&lt;br /&gt;
    ax_m = fig.add_subplot(nrows,ncols,i+1+ncols)&lt;br /&gt;
    ax_m.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_m.plot(m,color='darkgreen')&lt;br /&gt;
    ax_m.fill_between(np.arange(N),m,color='green',alpha=0.5,label=&amp;quot;Renda líquida: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax_m.legend(fontsize=10)&lt;br /&gt;
    &lt;br /&gt;
    if i == 0:&lt;br /&gt;
        ax_p.set_ylabel(&amp;quot;%&amp;quot;,fontsize=15)&lt;br /&gt;
        ax_m.set_ylabel(&amp;quot;$&amp;quot;, fontsize=15)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
ncols = 5  #Número de colunas da imagem // Número de snapshots&lt;br /&gt;
snapshots = np.array([0*dt,5*dt,10*dt,15*dt,20*dt])  #Vetor que aloca os tempos onde serão tirados os snapshots do sistema&lt;br /&gt;
&lt;br /&gt;
fig, big_axes = plt.subplots(nrows=2,ncols=1,figsize=(20,6),sharey=True)&lt;br /&gt;
titles = [&amp;quot;População (%)&amp;quot;,&amp;quot;Renda ($)&amp;quot;]&lt;br /&gt;
for row,big_ax in enumerate(big_axes):&lt;br /&gt;
    big_ax.set_title(titles[row],fontsize=22,y=1.15)&lt;br /&gt;
    big_ax.axis('off')&lt;br /&gt;
&lt;br /&gt;
count = 0&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if t in snapshots:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_grid(fig,p,m,count,t,ncols)&lt;br /&gt;
        count += 1&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
fig.subplots_adjust(hspace=0.55)&lt;br /&gt;
plt.savefig(&amp;quot;foo.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5325</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5325"/>
		<updated>2021-05-26T23:09:49Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 1D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
N indica o limite do eixo x. Quanto maior o seu valor, mais demorada fica a simulação. Porém, valores pequenos de N podem gerar resultados inconclusivos.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta x = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica a unidade infinitesimal do eixo x (neste caso, o único eixo do problema).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta t = 0.3 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica quanto tempo cada passo da simulação percorre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de renda.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de densidade populacional.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é um parâmetro intimamente ligado com o movimento da população para regiões com alta concentração de dinheiro. Nas palavras de Sayama,&amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt; indica a &amp;quot;habilidade que as pessoas da rede tem de 'sentir o cheiro' do dinheiro&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é utilizado no cálculo de &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, como descrito acima, seguindo a fórmula &amp;lt;math&amp;gt;v = \alpha \Delta t&amp;lt;/math&amp;gt;. Está relacionado com a velocidade do progresso da economia, ou seja, quão rápido cresce a renda em uma posição da malha através da influência da população. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é utilizado na fórmula &amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;, que indica a taxa de decaimento da renda em regiões da malha com baixa população.&lt;br /&gt;
&lt;br /&gt;
Estes parâmetros foram utilizados pois representam bem a característica do sistema de Keller-Segel que queremos representar: a formação de clusters de população na malha &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;. Uma nova combinação de parâmetros poderia resultar em resultados diferentes, mas que fogem do escopo deste projeto.&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; \mathcal{C}_1 = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; \mathcal{C}_2 = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida reduzida, pois o dinheiro decai a uma taxa &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt;, como já falado. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a taxa de evolução do sistema monetário em pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior largura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta condição inicial da população se assemelha muito à proposição inicial que Keller e Segel fizeram para um sistema celular, como descrito acima. Temos uma concentração homogênea de &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com formato gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de formato gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível mais uma vez a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema entre em um estado com somente um pico de formato gaussiano na população, e um pico na renda, com largura maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.zeros((parametros.N_y, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Código completo se encontra no Github.'''''&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
Nas figuras abaixo, sendo a primeira uma figura retirada do livro do Sayama &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;, e a segunda gerada utilizando o modelo construído, a fim de comparar com a primeira, observa-se, partindo de uma população constante na malha e de uma renda aleatoriamente distribuída, a formação de grupos (pontos mais escuros), deste modo provando que o modelo construído chega nos mesmos resultados que a referência.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-keller-segel.png|600px|thumb|center|Fonte: Sayama]]&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-pop-renda.png|600px|thumb|center|Clusters obtidos para os casos estudados, sob condições iniciais semelhantes às aplicadas por Sayama na imagem acima. Na imagem, observa-se, assim como na referência, o principal objetivo da aplicação do modelo: a presença de clusters de população sob a malha.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os gifs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
import imageio  &amp;quot;&amp;quot;&amp;quot;Biblioteca p/ gerar os gifs. Para instalar: pip install imageio&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_gif(p,m,t,images):&lt;br /&gt;
    fig,ax = plt.subplots(1,2,figsize=(10,5))&lt;br /&gt;
&lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[0].plot(100*p,color='purple')&lt;br /&gt;
    ax[0].set_ylabel(&amp;quot;%&amp;quot;)&lt;br /&gt;
    ax[0].grid(False)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[1].plot(m,color='darkgreen')&lt;br /&gt;
    ax[1].fill_between(np.arange(m.shape[0]),m,color='green',alpha=0.5,label=&amp;quot;Total money: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax[1].set_ylabel(&amp;quot;$&amp;quot;)&lt;br /&gt;
    ax[1].grid(False)&lt;br /&gt;
    ax[1].legend()&lt;br /&gt;
    &lt;br /&gt;
    plt.tight_layout()&lt;br /&gt;
    plt.savefig(imgname) #Salva o frame do sistema&lt;br /&gt;
    plt.close()&lt;br /&gt;
    &lt;br /&gt;
    images.append(imageio.imread(imgname)) #Adiciona a imagem na lista indicada&lt;br /&gt;
    os.remove(imgname) #Remove a imagem recém criada&lt;br /&gt;
    time.sleep(0.5)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
images = [] #Vetor para alocar as imagens que formarão o gif.&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if i % 10 == 0:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_gif(p,m,t,images)&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
imageio.mimsave(&amp;quot;foo.gif&amp;quot;, images,fps=3) #Ajustar fps conforme desejar. Quanto maior, + imagens/segundo&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os snapshots do sistema ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_grid(fig,p,m,i,t,ncols,nrows=2):&lt;br /&gt;
    #Population&lt;br /&gt;
    ax_p = fig.add_subplot(nrows,ncols,i+1)&lt;br /&gt;
    ax_p.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_p.plot(100*p,color='purple')&lt;br /&gt;
    ax_p.fill_between(np.arange(N),100*p,color='purple',alpha=0.5)&lt;br /&gt;
    &lt;br /&gt;
    #Money&lt;br /&gt;
    ax_m = fig.add_subplot(nrows,ncols,i+1+ncols)&lt;br /&gt;
    ax_m.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_m.plot(m,color='darkgreen')&lt;br /&gt;
    ax_m.fill_between(np.arange(N),m,color='green',alpha=0.5,label=&amp;quot;Renda líquida: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax_m.legend(fontsize=10)&lt;br /&gt;
    &lt;br /&gt;
    if i == 0:&lt;br /&gt;
        ax_p.set_ylabel(&amp;quot;%&amp;quot;,fontsize=15)&lt;br /&gt;
        ax_m.set_ylabel(&amp;quot;$&amp;quot;, fontsize=15)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
ncols = 5  #Número de colunas da imagem // Número de snapshots&lt;br /&gt;
snapshots = np.array([0*dt,5*dt,10*dt,15*dt,20*dt])  #Vetor que aloca os tempos onde serão tirados os snapshots do sistema&lt;br /&gt;
&lt;br /&gt;
fig, big_axes = plt.subplots(nrows=2,ncols=1,figsize=(20,6),sharey=True)&lt;br /&gt;
titles = [&amp;quot;População (%)&amp;quot;,&amp;quot;Renda ($)&amp;quot;]&lt;br /&gt;
for row,big_ax in enumerate(big_axes):&lt;br /&gt;
    big_ax.set_title(titles[row],fontsize=22,y=1.15)&lt;br /&gt;
    big_ax.axis('off')&lt;br /&gt;
&lt;br /&gt;
count = 0&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if t in snapshots:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_grid(fig,p,m,count,t,ncols)&lt;br /&gt;
        count += 1&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
fig.subplots_adjust(hspace=0.55)&lt;br /&gt;
plt.savefig(&amp;quot;foo.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5324</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=5324"/>
		<updated>2021-05-26T23:08:07Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 1D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
N indica o limite do eixo x. Quanto maior o seu valor, mais demorada fica a simulação. Porém, valores pequenos de N podem gerar resultados inconclusivos.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta x = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica a unidade infinitesimal do eixo x (neste caso, o único eixo do problema).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Delta t = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indica quanto tempo cada passo da simulação percorre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de renda.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constante de difusão da função de densidade populacional.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é um parâmetro intimamente ligado com o movimento da população para regiões com alta concentração de dinheiro. Nas palavras de Sayama,&amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt; indica a &amp;quot;habilidade que as pessoas da rede tem de 'sentir o cheiro' do dinheiro&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é utilizado no cálculo de &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, como descrito acima, seguindo a fórmula &amp;lt;math&amp;gt;v = \alpha \Delta t&amp;lt;/math&amp;gt;. Está relacionado com a velocidade do progresso da economia, ou seja, quão rápido cresce a renda em uma posição da malha através da influência da população. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é utilizado na fórmula &amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;, que indica a taxa de decaimento da renda em regiões da malha com baixa população.&lt;br /&gt;
&lt;br /&gt;
Estes parâmetros foram utilizados pois representam bem a característica do sistema de Keller-Segel que queremos representar: a formação de clusters de população na malha &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;. Uma nova combinação de parâmetros poderia resultar em resultados diferentes, mas que fogem do escopo deste projeto.&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; \mathcal{C}_1 = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; \mathcal{C}_2 = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida reduzida, pois o dinheiro decai a uma taxa &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt;, como já falado. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a taxa de evolução do sistema monetário em pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior largura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta condição inicial da população se assemelha muito à proposição inicial que Keller e Segel fizeram para um sistema celular, como descrito acima. Temos uma concentração homogênea de &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com formato gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de formato gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível mais uma vez a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema entre em um estado com somente um pico de formato gaussiano na população, e um pico na renda, com largura maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.zeros((parametros.N_y, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Código completo se encontra no Github.'''''&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
Nas figuras abaixo, sendo a primeira uma figura retirada do livro do Sayama &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;, e a segunda gerada utilizando o modelo construído, a fim de comparar com a primeira, observa-se, partindo de uma população constante na malha e de uma renda aleatoriamente distribuída, a formação de grupos (pontos mais escuros), deste modo provando que o modelo construído chega nos mesmos resultados que a referência.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-keller-segel.png|600px|thumb|center|Fonte: Sayama]]&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Clusters-pop-renda.png|600px|thumb|center|Clusters obtidos para os casos estudados, sob condições iniciais semelhantes às aplicadas por Sayama na imagem acima. Na imagem, observa-se, assim como na referência, o principal objetivo da aplicação do modelo: a presença de clusters de população sob a malha.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os gifs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
import imageio  &amp;quot;&amp;quot;&amp;quot;Biblioteca p/ gerar os gifs. Para instalar: pip install imageio&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_gif(p,m,t,images):&lt;br /&gt;
    fig,ax = plt.subplots(1,2,figsize=(10,5))&lt;br /&gt;
&lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[0].plot(100*p,color='purple')&lt;br /&gt;
    ax[0].set_ylabel(&amp;quot;%&amp;quot;)&lt;br /&gt;
    ax[0].grid(False)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda, t = {}&amp;quot;.format(round(t,1)))&lt;br /&gt;
    ax[1].plot(m,color='darkgreen')&lt;br /&gt;
    ax[1].fill_between(np.arange(m.shape[0]),m,color='green',alpha=0.5,label=&amp;quot;Total money: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax[1].set_ylabel(&amp;quot;$&amp;quot;)&lt;br /&gt;
    ax[1].grid(False)&lt;br /&gt;
    ax[1].legend()&lt;br /&gt;
    &lt;br /&gt;
    plt.tight_layout()&lt;br /&gt;
    plt.savefig(imgname) #Salva o frame do sistema&lt;br /&gt;
    plt.close()&lt;br /&gt;
    &lt;br /&gt;
    images.append(imageio.imread(imgname)) #Adiciona a imagem na lista indicada&lt;br /&gt;
    os.remove(imgname) #Remove a imagem recém criada&lt;br /&gt;
    time.sleep(0.5)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
images = [] #Vetor para alocar as imagens que formarão o gif.&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if i % 10 == 0:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_gif(p,m,t,images)&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
imageio.mimsave(&amp;quot;foo.gif&amp;quot;, images,fps=3) #Ajustar fps conforme desejar. Quanto maior, + imagens/segundo&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Script para gerar os snapshots do sistema ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot_grid(fig,p,m,i,t,ncols,nrows=2):&lt;br /&gt;
    #Population&lt;br /&gt;
    ax_p = fig.add_subplot(nrows,ncols,i+1)&lt;br /&gt;
    ax_p.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_p.plot(100*p,color='purple')&lt;br /&gt;
    ax_p.fill_between(np.arange(N),100*p,color='purple',alpha=0.5)&lt;br /&gt;
    &lt;br /&gt;
    #Money&lt;br /&gt;
    ax_m = fig.add_subplot(nrows,ncols,i+1+ncols)&lt;br /&gt;
    ax_m.set_title(&amp;quot;t = {}&amp;quot;.format(t),fontsize=18)&lt;br /&gt;
    ax_m.plot(m,color='darkgreen')&lt;br /&gt;
    ax_m.fill_between(np.arange(N),m,color='green',alpha=0.5,label=&amp;quot;Renda líquida: $ {}&amp;quot;.format(round(np.sum(m),2)))&lt;br /&gt;
    ax_m.legend(fontsize=10)&lt;br /&gt;
    &lt;br /&gt;
    if i == 0:&lt;br /&gt;
        ax_p.set_ylabel(&amp;quot;%&amp;quot;,fontsize=15)&lt;br /&gt;
        ax_m.set_ylabel(&amp;quot;$&amp;quot;, fontsize=15)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0. Varia conforme a condição inicial desejada.&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
ncols = 5  #Número de colunas da imagem // Número de snapshots&lt;br /&gt;
snapshots = np.array([0*dt,5*dt,10*dt,15*dt,20*dt])  #Vetor que aloca os tempos onde serão tirados os snapshots do sistema&lt;br /&gt;
&lt;br /&gt;
fig, big_axes = plt.subplots(nrows=2,ncols=1,figsize=(20,6),sharey=True)&lt;br /&gt;
titles = [&amp;quot;População (%)&amp;quot;,&amp;quot;Renda ($)&amp;quot;]&lt;br /&gt;
for row,big_ax in enumerate(big_axes):&lt;br /&gt;
    big_ax.set_title(titles[row],fontsize=22,y=1.15)&lt;br /&gt;
    big_ax.axis('off')&lt;br /&gt;
&lt;br /&gt;
count = 0&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    if t in snapshots:  #Gera 1 imagem a cada 10 iterações, para não gerar um .gif muito pesado.&lt;br /&gt;
        plot_grid(fig,p,m,count,t,ncols)&lt;br /&gt;
        count += 1&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
fig.subplots_adjust(hspace=0.55)&lt;br /&gt;
plt.savefig(&amp;quot;foo.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5322</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5322"/>
		<updated>2021-05-26T23:05:03Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo. A temperatura no caso deste modelo, vai ditar a distribuição de estratégias: para uma temperatura baixa, as estratégias associadas ao spin up dominarão; já para uma temperatura mais elevada, as estratégias associadas ao spin down predominarão.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5320</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5320"/>
		<updated>2021-05-26T22:52:41Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;. Podemos interpretar a temperatura nesse sistema como se fosse a velocidade com que as transações acontecem: para uma temperatura baixa, os agentes trocariam suas estratégias mais devagar, por exemplo.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5319</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5319"/>
		<updated>2021-05-26T22:47:53Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações e o Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo de interação é tomado como uma constante &amp;lt;math&amp;gt;J_{ij} = 1&amp;lt;/math&amp;gt; para vizinhos e &amp;lt;math&amp;gt;J_{ij} = 0&amp;lt;/math&amp;gt; para os demais spins, e ele é responsável pela indução de ordem ferromagnética local.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5318</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5318"/>
		<updated>2021-05-26T22:44:12Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a magnitude de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tendem a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5317</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5317"/>
		<updated>2021-05-26T22:43:27Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j ,&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases} ,&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5315</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5315"/>
		<updated>2021-05-26T22:40:00Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising&amp;lt;ref name='ising'&amp;gt;https://en.wikipedia.org/wiki/Ising_model&amp;lt;/ref&amp;gt;. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''2h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 85%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5101</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=5101"/>
		<updated>2021-05-24T23:35:17Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações e o Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Em todos os casos, a simulação foi feita usando a dinâmica de banho térmico já apresentada, juntamente com Monte Carlo. Para cada passo (''sweep'') de MC, sorteia-se várias posições no sistema e aplica-se a dinâmica de ''heat-bath'' sobre cada uma, calculando, após isso, a orientação do spin.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos, para que fiquem na mesma escala:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE)&amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;. Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt; &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a Transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 80%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Objeto que implementa o Modelo de Bornholdt em Python===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class Bornholdt():&lt;br /&gt;
    def __init__(self,N_rows,N_cols,T):&lt;br /&gt;
        self.L = N_rows     #Size of mesh in X&lt;br /&gt;
        self.N = N_cols     #Size of mesh in Y&lt;br /&gt;
        self.beta = 1/T     #beta ~ 1/T&lt;br /&gt;
        self.state = init_state(self.L,self.N)     #Initialize the network&lt;br /&gt;
        self.Mag = calc_mag(self.state)            #Magnetization for a specific state&lt;br /&gt;
&lt;br /&gt;
    def update_spins(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Provides a single update in the network &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = heat_bath(self.state,self.beta)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
&lt;br /&gt;
    def reset_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Reset the grid to the initial state &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self.state = init_state(self.L,self.N)&lt;br /&gt;
        self.Mag = calc_mag(self.state)&lt;br /&gt;
        &lt;br /&gt;
    def magnetization(self,mcSteps,plot=False,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Calculates the magnetization and updates the spins of system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = int(mcSteps/number_prints)&lt;br /&gt;
        Magnetism = np.zeros(mcSteps) &lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % n == 0:&lt;br /&gt;
                print(&amp;quot;MC Sweep nº: {}&amp;quot;.format(j))&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
            Magnetism[j] = self.Mag&lt;br /&gt;
        #Plot&lt;br /&gt;
        if plot:&lt;br /&gt;
            fig,ax = plt.subplots(1,1,figsize=(8,4))&lt;br /&gt;
            ax.set_ylabel(&amp;quot;M(t)&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.set_xlabel(&amp;quot;t&amp;quot;,fontsize=12)&lt;br /&gt;
            ax.plot(Magnetism,lw=0.8,color='black')&lt;br /&gt;
            ax.set_xlim(0,len(Magnetism))&lt;br /&gt;
            plt.tight_layout()&lt;br /&gt;
            plt.show()&lt;br /&gt;
        return Magnetism&lt;br /&gt;
    &lt;br /&gt;
    def print_state(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Plots the current status of the grid, in a 2D mesh &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        &lt;br /&gt;
        fig,ax = plt.subplots(1,1,figsize=(3,3))&lt;br /&gt;
        ax.set_xticks([])&lt;br /&gt;
        ax.set_yticks([])&lt;br /&gt;
        ax.pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
        &lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
    &lt;br /&gt;
    def plot_grid(self,mcSteps,n_plots,number_prints=8):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot; Built a grid with 2D meshs plots, perfect to visualize the system. &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        n = n_plots**2&lt;br /&gt;
        X,Y = np.meshgrid(np.arange(self.L),np.arange(self.N))&lt;br /&gt;
        fig,ax = plt.subplots(n_plots,n_plots,figsize=(8,8))&lt;br /&gt;
        print_graph = int(mcSteps/n)&lt;br /&gt;
        snapshots = []&lt;br /&gt;
        #Constructing snapshots list&lt;br /&gt;
        for i in np.arange(mcSteps):&lt;br /&gt;
            if (i % print_graph==0) and (len(snapshots) &amp;lt; n):&lt;br /&gt;
                snapshots.append(i)&lt;br /&gt;
        #Heat-Bath&lt;br /&gt;
        count = 0&lt;br /&gt;
        for j in np.arange(mcSteps):&lt;br /&gt;
            if j % int(mcSteps/number_prints) == 0:&lt;br /&gt;
                print(&amp;quot;-- MC sweep nº {}...&amp;quot;.format(j))&lt;br /&gt;
            if j in snapshots:&lt;br /&gt;
                #Plot config.&lt;br /&gt;
                x_i = int(count/n_plots)%n_plots&lt;br /&gt;
                y_i = int(count%n_plots)&lt;br /&gt;
                ax[x_i,y_i].pcolor(X, Y, self.state, cmap=plt.cm.Greys,shading='auto',linewidth=0,rasterized=True)&lt;br /&gt;
                ax[x_i,y_i].set_title(&amp;quot;t = {}&amp;quot;.format(j),fontsize=22)&lt;br /&gt;
                ax[x_i,y_i].set_xticks([])&lt;br /&gt;
                ax[x_i,y_i].set_yticks([])&lt;br /&gt;
                count += 1&lt;br /&gt;
            self.update_spins()&lt;br /&gt;
        #Plot config.&lt;br /&gt;
        plt.tight_layout()&lt;br /&gt;
        plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt com variação de opiniões ao longo da simulação (Julia)===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;julia&amp;quot;&amp;gt;&lt;br /&gt;
using Statistics&lt;br /&gt;
println(&amp;quot;Statistics imported sucessfully&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
function calc_ret(M)&lt;br /&gt;
    N = length(M)&lt;br /&gt;
    corrected_M = []&lt;br /&gt;
    for m in M&lt;br /&gt;
        if m == 0.0&lt;br /&gt;
            append!(corrected_M,0.000001)&lt;br /&gt;
        else&lt;br /&gt;
            append!(corrected_M,m)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    r = []&lt;br /&gt;
    for i in 2:N&lt;br /&gt;
        ret = log(abs(corrected_M[i]/corrected_M[i-1]))&lt;br /&gt;
        append!(r,ret)&lt;br /&gt;
    end&lt;br /&gt;
    r_ = mean(r)&lt;br /&gt;
    sigma_r = std(r)&lt;br /&gt;
    r_norm = [(ret-r_)/sigma_r for ret in r]&lt;br /&gt;
    return r_norm&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function agent_opinion(p1,p2)&lt;br /&gt;
    opinion = rand()&lt;br /&gt;
    if opinion &amp;lt;= p1&lt;br /&gt;
        return +1,+1.0 #Strategy 1 - Player that wants to join the minority (fundamentalist)&lt;br /&gt;
    elseif opinion &amp;lt;= (p2+p1)&lt;br /&gt;
        return +2,-1.0 #Strategy 2 - Player wants to join majority of agents (chartist)&lt;br /&gt;
    else&lt;br /&gt;
        return +3,(2*rand(0:1) - 1) #Strategy 3 - Dumb irrational player&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function flip_opinion(current_opinion)&lt;br /&gt;
    opinions = [1,2,3]&lt;br /&gt;
    d = Dict()&lt;br /&gt;
    d[1] = +1.0&lt;br /&gt;
    d[2] = -1.0&lt;br /&gt;
    d[3] = (rand() - 0.5)&lt;br /&gt;
    splice!(opinions,Int64(current_opinion))&lt;br /&gt;
    n = length(opinions)&lt;br /&gt;
    new_opinion = rand(1:n)&lt;br /&gt;
    return new_opinion,d[new_opinion]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function count_states(opinion_mesh)&lt;br /&gt;
    N,L = size(opinion_mesh) &lt;br /&gt;
    opinion1 = 0&lt;br /&gt;
    opinion2 = 0&lt;br /&gt;
    opinion3 = 0&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            if opinion_mesh[i,j] == 1&lt;br /&gt;
                opinion1 += 1/(N*L)&lt;br /&gt;
            elseif opinion_mesh[i,j] == 2&lt;br /&gt;
                opinion2 += 1/(N*L)&lt;br /&gt;
            else&lt;br /&gt;
                opinion3 += 1/(N*L)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return [opinion1,opinion2,opinion3]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_C(spins,p1,p2)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    C = zeros(N,L)&lt;br /&gt;
    opinions = [0,0,0]&lt;br /&gt;
    opinion_mesh = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            opinion, C_value = agent_opinion(p1,p2)&lt;br /&gt;
            C[i,j] = C_value&lt;br /&gt;
            opinion_mesh[i,j] = opinion&lt;br /&gt;
            opinions[opinion] += 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return opinions,C,opinion_mesh&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function init_network(N,L)&lt;br /&gt;
    spins = zeros(N,L)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            r = rand()&lt;br /&gt;
            if r &amp;lt; 0.5&lt;br /&gt;
                spins[i,j] = -1&lt;br /&gt;
            else&lt;br /&gt;
                spins[i,j] = +1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function find_nb(spins,a,b)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    #Adjusting for a&lt;br /&gt;
    if (a-1) &amp;lt;= 0&lt;br /&gt;
        back_a = N&lt;br /&gt;
    else&lt;br /&gt;
        back_a = a-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (a+1) &amp;gt; N&lt;br /&gt;
        forward_a = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_a = a+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    #Adjusting for b&lt;br /&gt;
    if (b-1) &amp;lt;= 0&lt;br /&gt;
        back_b = N&lt;br /&gt;
    else&lt;br /&gt;
        back_b = b-1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if (b+1) &amp;gt; L&lt;br /&gt;
        forward_b = 1&lt;br /&gt;
    else&lt;br /&gt;
        forward_b = b+1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    left = spins[a,back_b]&lt;br /&gt;
    right = spins[a,forward_b]&lt;br /&gt;
    top = spins[back_a,b]&lt;br /&gt;
    bottom = spins[forward_a,b]&lt;br /&gt;
    return [left,right,top,bottom]&lt;br /&gt;
end    &lt;br /&gt;
&lt;br /&gt;
function calc_spin(arg)&lt;br /&gt;
    p = 1 / (1 + exp((-1)*arg))&lt;br /&gt;
    r = rand()&lt;br /&gt;
    if r &amp;lt; p&lt;br /&gt;
        spin = +1&lt;br /&gt;
    else&lt;br /&gt;
        spin = -1&lt;br /&gt;
    end&lt;br /&gt;
    return spin&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    J = 1&lt;br /&gt;
    a_vec = rand(1:N,N^2)&lt;br /&gt;
    b_vec = rand(1:L,L^2)&lt;br /&gt;
    for (a,b) in zip(a_vec,b_vec)&lt;br /&gt;
        s = spins[a,b]&lt;br /&gt;
        nb = sum(find_nb(spins,a,b))&lt;br /&gt;
        local_field_h = J*nb - alpha*C[a,b]*sum(spins)/(N*L)&lt;br /&gt;
        spins[a,b] = calc_spin(2*beta*local_field_h)&lt;br /&gt;
        if opinion_mesh[a,b] == 3&lt;br /&gt;
            C[a,b] = (2*rand(0:1) - 1)&lt;br /&gt;
        end    &lt;br /&gt;
        if change_opinions&lt;br /&gt;
            if s != spins[a,b]&lt;br /&gt;
                (opinion,C_value) = flip_opinion(opinion_mesh[a,b])&lt;br /&gt;
                C[a,b] = C_value #If the agent changes signal, he changes strategy&lt;br /&gt;
                opinion_mesh[a,b] = opinion&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return spins&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function calc_mag(spins)&lt;br /&gt;
    N,L = size(spins)&lt;br /&gt;
    m = sum(spins)&lt;br /&gt;
    return m / (N*L)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function write_to_file(filename,data1,data2)&lt;br /&gt;
    N = length(data1)&lt;br /&gt;
    open(filename,&amp;quot;w&amp;quot;) do file&lt;br /&gt;
        write(file,&amp;quot;M(t),r(t)\n&amp;quot;)&lt;br /&gt;
        write(file,(string(data1[1])*&amp;quot;,-\n&amp;quot;))&lt;br /&gt;
        for i in 2:N&lt;br /&gt;
            write(file,string(data1[i])*&amp;quot;,&amp;quot;*string(data2[i-1])*&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_state(filename,C)&lt;br /&gt;
    N,L = size(C)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(C[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    close(file)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function print_opinions(filename,opinions)&lt;br /&gt;
    N,L = size(opinions)&lt;br /&gt;
    file = open(filename,&amp;quot;w&amp;quot;)&lt;br /&gt;
    for i in 1:N&lt;br /&gt;
        for j in 1:L&lt;br /&gt;
            write(file,string(opinions[i,j])*&amp;quot;,&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        write(file,&amp;quot;\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
N = 32&lt;br /&gt;
L = 32&lt;br /&gt;
mcSteps = 3000&lt;br /&gt;
n_prints = Int(floor(mcSteps/4))&lt;br /&gt;
T = 1.5&lt;br /&gt;
beta = 1/T&lt;br /&gt;
alpha = 4.0&lt;br /&gt;
&lt;br /&gt;
p1 = 1/3 # Prob. opinion #1: fundamentalist&lt;br /&gt;
p2 = 1/3 # Prob. opinion #2: chartist&lt;br /&gt;
change_opinions = true # If true, opinion of agents can change during simulation.&lt;br /&gt;
&lt;br /&gt;
spins = init_network(N,N)&lt;br /&gt;
M = zeros(mcSteps)&lt;br /&gt;
opinions,C,opinion_mesh = get_C(spins,p1,p2)&lt;br /&gt;
&lt;br /&gt;
println(&amp;quot;Network opinions:&amp;quot;)&lt;br /&gt;
for (i,opinion) in enumerate(opinions)&lt;br /&gt;
    println(&amp;quot;Opinion &amp;quot;,i,&amp;quot;: &amp;quot;,100*opinion/(N*L),&amp;quot; %&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
println(&amp;quot;====================================&amp;quot;)&lt;br /&gt;
perc_opinions = zeros(mcSteps,3)&lt;br /&gt;
plot_grid = floor(mcSteps/15)&lt;br /&gt;
shots = [1]&lt;br /&gt;
append!(shots,[i*plot_grid for i in 1:15])&lt;br /&gt;
count = 0&lt;br /&gt;
&lt;br /&gt;
for i in 1:mcSteps&lt;br /&gt;
    if (i in shots)&lt;br /&gt;
        println(&amp;quot;----- Grid in &amp;quot;,i)&lt;br /&gt;
        filename = &amp;quot;state_MC&amp;quot;*string(count)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
        print_state(filename,opinion_mesh)&lt;br /&gt;
        global count += 1&lt;br /&gt;
    end&lt;br /&gt;
    percs = count_states(opinion_mesh)&lt;br /&gt;
    for j in 1:3&lt;br /&gt;
        perc_opinions[i,j] = percs[j]&lt;br /&gt;
    end&lt;br /&gt;
    heat_bath(spins,beta,alpha,C,change_opinions)&lt;br /&gt;
    M[i] = calc_mag(spins)&lt;br /&gt;
    if i % n_prints == 0&lt;br /&gt;
        println(&amp;quot;-- Sweep nº &amp;quot;,i,&amp;quot; concluded.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
filename = &amp;quot;mag_ret_N&amp;quot;*string(N*L)*&amp;quot;.txt&amp;quot;&lt;br /&gt;
write_to_file(filename,M,calc_ret(M))&lt;br /&gt;
print_opinions(&amp;quot;opinions_N&amp;quot;*string(N^2)*&amp;quot;.txt&amp;quot;,perc_opinions)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementação do Modelo de Bornholdt simples em C===&lt;br /&gt;
OBS: código não otimizado.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 32&lt;br /&gt;
#define L 32&lt;br /&gt;
#define MAX_STRING_SIZE 15&lt;br /&gt;
#define NUMBER_OF_PLOTS 9&lt;br /&gt;
int spins[N][L];&lt;br /&gt;
&lt;br /&gt;
double rng(){&lt;br /&gt;
    return (float)rand()/RAND_MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int int_rng(int max_value){&lt;br /&gt;
    return rand() % max_value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initialize_network(){&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            spins[i][j]=2*int_rng(2)-1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double sum_array(){&lt;br /&gt;
    double sum = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            sum = sum + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int calc_spin(double arg){&lt;br /&gt;
    double p = 1 / (1 + exp(arg));&lt;br /&gt;
    double r = rng();&lt;br /&gt;
    if(r &amp;lt; p){&lt;br /&gt;
        return +1;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double calc_magnetization(){&lt;br /&gt;
    double m = 0.0;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            m = m + spins[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return (double) (m/(L*N));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_state(char filename[]){&lt;br /&gt;
    FILE *grid;&lt;br /&gt;
    grid = fopen(filename,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            fprintf(grid,&amp;quot;%d,&amp;quot;,spins[i][j]);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(grid,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    fclose(grid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void heat_bath(double beta){&lt;br /&gt;
    double alpha = 4.0;&lt;br /&gt;
    double J = 1.0;&lt;br /&gt;
    int a;&lt;br /&gt;
    int b;&lt;br /&gt;
    int s;&lt;br /&gt;
    int nb_left,nb_right,nb_top,nb_bottom,sum_nb;&lt;br /&gt;
    double arg;&lt;br /&gt;
    for(int i=0;i&amp;lt;N;i++){&lt;br /&gt;
        for(int j=0;j&amp;lt;L;j++){&lt;br /&gt;
            a = int_rng(N);&lt;br /&gt;
            b = int_rng(L);&lt;br /&gt;
            s = spins[a][b];&lt;br /&gt;
            nb_top = spins[(a+N-1)%N][b];&lt;br /&gt;
            nb_bottom = spins[(a+1)%N][b];&lt;br /&gt;
            nb_left = spins[a][(b+L-1)%L];&lt;br /&gt;
            nb_right = spins[a][(b+1)%L];&lt;br /&gt;
            sum_nb = nb_left+nb_top+nb_right+nb_bottom;&lt;br /&gt;
            arg = (double)2*beta*(J*sum_nb - alpha*s*abs(sum_array(*spins))/(L*N));&lt;br /&gt;
            spins[a][b] = calc_spin(-arg);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    //!Declarate variables&lt;br /&gt;
    clock_t begin;&lt;br /&gt;
    clock_t end;&lt;br /&gt;
    double T = 1.5;&lt;br /&gt;
    double beta = 1/T;&lt;br /&gt;
    int mcSteps = 1000;&lt;br /&gt;
    int n_prints = (int)(mcSteps/5);&lt;br /&gt;
    char filename[][MAX_STRING_SIZE] = {&amp;quot;grid1.txt&amp;quot;,&amp;quot;grid2.txt&amp;quot;,&amp;quot;grid3.txt&amp;quot;,&amp;quot;grid4.txt&amp;quot;,&amp;quot;grid5.txt&amp;quot;,&amp;quot;grid6.txt&amp;quot;,&amp;quot;grid7.txt&amp;quot;,&amp;quot;grid8.txt&amp;quot;,&amp;quot;grid9.txt&amp;quot;};&lt;br /&gt;
    int snapshots[NUMBER_OF_PLOTS];&lt;br /&gt;
    for(int i=0;i&amp;lt;NUMBER_OF_PLOTS;i++){&lt;br /&gt;
        snapshots[i] = i*(mcSteps/NUMBER_OF_PLOTS);&lt;br /&gt;
    }&lt;br /&gt;
    int plot_index = 0;&lt;br /&gt;
    FILE *mag_file;&lt;br /&gt;
    mag_file = fopen(&amp;quot;magnetization.dat&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    //!Init. Network&lt;br /&gt;
    initialize_network();&lt;br /&gt;
    end = clock();&lt;br /&gt;
    printf(&amp;quot;Network initiated\n&amp;quot;);&lt;br /&gt;
    printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    //////////////////////////////////////////////////////////////////////!&lt;br /&gt;
    begin = clock();&lt;br /&gt;
    for(int j=0;j&amp;lt;mcSteps;j++){&lt;br /&gt;
        if(j % n_prints == 0){&lt;br /&gt;
            printf(&amp;quot;Simulation %d...\n&amp;quot;,j);&lt;br /&gt;
        }&lt;br /&gt;
        if(j == snapshots[plot_index]){&lt;br /&gt;
            printf(&amp;quot;-- Building %s...\n&amp;quot;,filename[plot_index]);&lt;br /&gt;
            print_state(filename[plot_index]);&lt;br /&gt;
            plot_index++;&lt;br /&gt;
        }&lt;br /&gt;
        //!Heat-Bath&lt;br /&gt;
        heat_bath(beta);&lt;br /&gt;
        //!Magnetization&lt;br /&gt;
        fprintf(mag_file,&amp;quot;%lf\n&amp;quot;,calc_magnetization());&lt;br /&gt;
    }&lt;br /&gt;
    fclose(mag_file);&lt;br /&gt;
    end = clock();&lt;br /&gt;
    if(N&amp;gt;40){&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf min\n&amp;quot;, (double)(end-begin)/(60*CLOCKS_PER_SEC));&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Executed time: %lf s\n&amp;quot;, (double)(end-begin)/CLOCKS_PER_SEC);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;==========================================================\n&amp;quot;);&lt;br /&gt;
    system(&amp;quot;python plot.py&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4928</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4928"/>
		<updated>2021-05-24T18:32:39Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos_.5B4.5D|retornos]] dos preços e uma alta correlação da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Mais detalhes sobre como a opinião de um agente influencia no sistema estão na seção de [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Varia.C3.A7.C3.A3o_da_opini.C3.A3o_dos_agentes|opinião dos agentes]]&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 80%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4922</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4922"/>
		<updated>2021-05-24T18:20:42Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t), \qquad \text{se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 80%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4921</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4921"/>
		<updated>2021-05-24T18:20:10Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
Em 2002, Stefan Bornholdt apresentou um modelo de spins motivado pela dinâmica de agentes no mercado financeiro, que retornava observações observadas em situações reais, como distribuição de retorno de caudas pesadas e clusterização de volatilidade.&amp;lt;ref name='modelo'&amp;gt;Bornholdt, Stefan. (2011). Expectation bubbles in a spin model of markets: Intermittency from frustration across scales. International Journal of Modern Physics C. 12. 10.1142/S0129183101001845. &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é, então, apresentar o Modelo de Bornholdt como alternativa para a construção de um mercado financeiro artificial com características observadas em mercados reais. Dentre os principais resultados obtidos, destaca-se a formação de estados metaestáveis, distribuição de retornos de cauda pesada, e clusters de volatilidade.&lt;br /&gt;
&lt;br /&gt;
Por fim, também é apresentado uma alternativa para o uso do Modelo de Bornholdt, analisando a opinião dos agentes da rede, e como estas influenciam no resultado final.&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi &amp;lt;ref name='bonrholdt12'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Scaling and Criticality in a Stochastic Multi-Agent Model of a Financial Market. Nature. 397. 10.1038/17290.&amp;lt;/ref&amp;gt; &amp;lt;ref name='bonrholdt13'&amp;gt;Lux, Thomas &amp;amp; Marchesi, Michele. (1998). Volatility Clustering in Financial Markets: A MicroSimulation of Interacting Agents. International Journal of Theoretical and Applied Finance. 3. 10.1142/S0219024900000826.&amp;lt;/ref&amp;gt; que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de distribuição de potências (cauda pesada) dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \qquad \text{se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math display='inline'&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math display='inline'&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. &amp;lt;ref name = 'fatoestilizado'&amp;gt; Da Cunha, Carlo &amp;amp; Silva, Roberto. (2019). Relevant Stylized Facts About Bitcoin: Fluctuations, First Return Probability, and Natural Phenomena.&amp;lt;/ref&amp;gt; Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
Com o intuito de construir uma rede de opiniões mistas (como é em casos de mercados reais), foram testadas várias combinações de porcentagens de opiniões na rede, até se encontrar uma que reproduzisse resultados muito semelhantes à de dados reais.&lt;br /&gt;
&lt;br /&gt;
Utilizando aproximadamente 80% de agentes com opinião 3, 10% de opinião 1 e 5% de opinião 2, obteve-se o resultado ilustrado nos gráficos abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns pontos importantes:&lt;br /&gt;
*provavelmente, se fossem feitos mais testes de combinações de probabilidade, chegaria-se a um resultado que encaixaria muito bem com alguma das curvas de dados reais. Porém, o intuito do trabalho, como dito anteriormente, não é replicar exatamente o que acontece com o mercado X ou Y, mas sim produzir um mercado artificial com características muito parecidas às observadas em mercados reais.&lt;br /&gt;
*os retornos apresentam transições de estados de alta e baixa muito mais agudas do que casos reais. É quase como se não houvesse meio termo, ou o agente ganha muito, ou perde muito, ou não ganha nada. Uma limitação do modelo.&lt;br /&gt;
*a distribuição de retornos apresenta cauda pesada, como observado em mercados reais.&lt;br /&gt;
&lt;br /&gt;
A simulação acima indica que, para melhor simular mercados reais, a maioria dos agentes devem atuar de maneira irracional, enquanto que uma parcela de aproximadamente 10% atua de acordo com a minoria e aproximadamente 5% com a maioria.&lt;br /&gt;
&lt;br /&gt;
Pode-se, também, permitir que os agentes troquem de opinião de forma minimamente racional ao longo da simulação. Deste modo, sempre que um agente &amp;quot;errar&amp;quot; no palpite (i.e. trocar a sua orientação de spin), ele escolhe outra opinião para seguir, até que erre novamente. A escolha da opinião é feita de forma aleatória pelo agente (portanto, não é 100% racional). O resultado para diferentes condições iniciais encontra-se nas figuras abaixo:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Sit1 igual.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial igual para as 3 opiniões.]] &lt;br /&gt;
! [[Arquivo:Sit2 op3.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 3.]] &lt;br /&gt;
! [[Arquivo:Sit3 op1.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 1.]]&lt;br /&gt;
! [[Arquivo:Sit4 op2.png|270px|thumb|center|Porcentagem de composição da rede para cada opinião ao longo da simulação, com condição inicial de 100% opinião 2.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observando a figura acima, nota-se a tendência do sistema em colapsar para um estado onde a maioria dos agentes têm opinião 2, até mesmo quando inicia-se com 0 agentes partilhando desta opinião.&lt;br /&gt;
&lt;br /&gt;
Relembrando, a opinião 2 refere-se aos agentes que têm opinião ajustada pela maioria. Em todas as simulações feitas, após um certo tempo transcorrido da simulação, 100% da rede é composta por esta opinião, o que implica em um estado de consenso da rede quanto à opinião de compra ou venda sobre um ativo. Faz muito sentido que a tendência natural do sistema seja colapsar para esta opinião, porque nela todos os agentes saem sem perder dinheiro da negociação (em compensação, também ganham um retorno ínfimo).&lt;br /&gt;
&lt;br /&gt;
O problema é que este resultado não pode ser observado na prática, pois o modelo de Bornholdt tem a limitação de não levar em consideração fatores como crises financeiras, por exemplo, de modo que o preço do ativo é reflexo exclusivamente da opinião dos agentes. Caso o mercado financeiro real fosse comportado desta forma, bastaria que todos os investidores tomassem a mesma opinião para que não houvesse prejuízo.&lt;br /&gt;
&lt;br /&gt;
Porém, na vida real, a imprevisibilidade de ativos acaba compensando alguns agentes a terem opinião contrária à maioria, de modo que, quando um ativo em alta cai na bolsa, estes ganham um retorno consideravelmente maior do que os que optaram por partilhar da mesma opinião.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, têm-se uma malha que representa o sistema, onde cada pixel representa um agente, e as cores indicam qual a opinião de cada agente ao longo do tempo. Foram utilizadas as mesmas condições iniciais que no exemplo acima.&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mesh equal.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com o mesmo número de agentes para cada opinião em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op3.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 3 em t=0.]] &lt;br /&gt;
! [[Arquivo:Mesh op1.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 1 em t=0.]]&lt;br /&gt;
! [[Arquivo:Mesh op2.png|270px|thumb|center|Comportamento dos agentes ao longo do tempo, com 100% de agentes de opinião 2 em t=0.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A figura reforça o que já foi confirmado antes, sobre o sistema tender a colapsar inteiramente para a opinião 2. Mais um fator interessante que pode ser observado está na concentração de agentes de opinião 1 ao longo do tempo. Há um momento logo no início das simulações onde há a formação de pequenos clusters de opinião 1, que logo se dissolvem e viram de opinião 2.&lt;br /&gt;
&lt;br /&gt;
No início da simulação, ainda há um breve retorno para agentes que apostam contra a maioria, o que justifica a formação destes aglomerados. Porém, com o passar do tempo e a maioria da rede sendo formada pela opinião 2, estes clusters somem, e a malha fica 100% coberta de opinião 2.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
Tendo em vista o que foi abordado até aqui, algumas conclusões podem ser tiradas:&lt;br /&gt;
&lt;br /&gt;
*simulações com um número de agentes da ordem de 1024 (grade 32x32) descrevem melhor um mercado financeiro, visto que apresentam ''clusters'' de volatilidade e possuem uma distribuição de retornos próxima a de um índice de mercado;&lt;br /&gt;
*através de simulações, verificou-se o perfil de investidores em mercados reais, baseado em suas opiniões. Em geral, a população que investe em ações é distribuída de forma que a grande maioria (aproximadamente 80%) atua de forma irracional (sem uma estratégia), uma parcela que gira em torno de 10% atua como fundamentalista (atua de acordo com a minoria do sistema) e aproximadamente 5% atua de maneira chartista (segue a opinião da maioria).&lt;br /&gt;
*ao permitir que agentes troquem de opinião livremente durante a simulação, observou-se a tendência do sistema de colapsar para um estado em que todos ou quase todos os agentes sigam o que a maioria do sistema está fazendo. Esta situação não descreve bem um sistema real, já que em um sistema financeiro existem fatores imprevisíveis que compõem o preço de ativos, não somente a opinião dos agentes. A partir do momento em que há possibilidade da minoria lucrar, surgem agentes de opinião 1. Também observou-se que, ao &amp;quot;forçar&amp;quot; que um agente que perde troque de opinião, elimina-se do sistema a opinião 3, ou seja, todos os agentes tornam-se minimamente racionais.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4803</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4803"/>
		<updated>2021-05-24T01:20:17Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Introdução */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \qquad \text{se} \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4802</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4802"/>
		<updated>2021-05-24T01:16:40Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações e o Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\beta = \frac{1}{k_B T}&amp;lt;/math&amp;gt;. Neste trabalho, por simplicidade assumiu-se que &amp;lt;math&amp;gt;k_B = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4800</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4800"/>
		<updated>2021-05-24T01:07:53Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Introdução==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações e o Modelo de Bornholdt===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4798</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4798"/>
		<updated>2021-05-24T01:05:00Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam adotar duas estratégias diferentes, sendo possível agora adotar &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4796</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4796"/>
		<updated>2021-05-24T01:00:34Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j}^N J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j}^N S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam duas estratégias diferentes, sendo possível agora adotar a estratégia &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4795</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4795"/>
		<updated>2021-05-24T00:58:22Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam duas estratégias diferentes, sendo possível agora adotar a estratégia &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
Por fim, podemos definir regras para a transição entre as duas estratégias estratégias, onde cada ''trader'' tenderá a adotar uma estratégia ótima. Consideremos o cenário mais simples para trocas de estratégia: um agente no grupo majoritário frequentemente tenderá a mudar para o grupo minoritário, por exemplo para apostar em um comodity que ainda não está na moda (e possivelmente escapar de um crash do seu bem mais popular no momento). Por outro lado, um agente que se encontra no grupo minoritário (portanto esperando retornos futuros) pode não estar satisfeito com seus retornos atuais. Em resumo agentes nos grupos majoritários sempre irão escolher a estratégia &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt;, enquanto a minoria irá escolher &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;. Cada agente escolhe uma estratégia arriscada a fim de aumentar seus retornos. A dinâmica da transição de estratégias é dada pela expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;C_i(t + 1) = -C_i(t) \text{ se } \alpha C_i(t) \sum_{j=1}^N S_j(t) &amp;lt; 0.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4787</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4787"/>
		<updated>2021-05-24T00:43:00Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Cenários  de Simulação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Um cenário mais interessante, é permitir que os agentes possam duas estratégias diferentes, sendo possível agora adotar a estratégia &amp;lt;math&amp;gt;C_i(t) = -1&amp;lt;/math&amp;gt;, que corresponde a um acoplamento ferromagnético com a magnetização global. Essa estratégia é chamada de chartista, visto que os agentes tendem a seguir a opinião da maioria dos ''traders''.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Mixed opinions.png|400px|thumb|center|Simulação com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
! [[Arquivo:Mixed opinions kde.png|400px|thumb|center|Distribuição de retornos com 15% da rede contendo agentes de opinião 1, 5% de opinião 2 e 80% de opinião 3]] &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4782</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4782"/>
		<updated>2021-05-24T00:36:47Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
====Cenários  de Simulação====&lt;br /&gt;
Vários cenários podem ser analisados, dependendo do valor e da dinâmica das estratégias. Consideremos o caso mais simples, em que &amp;lt;math&amp;gt;C_i(t) = 1 \forall i,t&amp;lt;/math&amp;gt;. Cada agente, apesar do acoplamento ferromagnético local com os primeiros vizinhos, tem um acoplamento antiferromagnético com a magnetização. Esta dinâmica corresponde a ''traders'' que em adição a um nível básico de ferromagnetismo, ou seja, tendem a adotar estratégias parecidas com seus vizinhos, também têm o desejo de se juntar a minoria global, por exemplo a fim de investir em possíveis ganhos futuros. Portanto, ''traders'' com &amp;lt;math&amp;gt;C_i(t) = 1&amp;lt;/math&amp;gt; podem ser chamados de fundamentalistas. Se todos os agentes adotam esta estratégia, a dinâmica global do sistema tenderá rápidamente a um estado de magnetização quase zero, mesmo para temperaturas abaixo da temperatura crítica &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor. Não é um sistema muito realista pois os retornos não oscilam tão rapidamente assim.&lt;br /&gt;
&lt;br /&gt;
Já no sistema composto apenas da opinião 2, há uma estabilidade quase que instantânea. Como todos os agentes seguem a maioria, uma vez atingido um determinado número mínimo de agentes com a mesma opinião, todos os outros passam a segui-la. E como não há agentes que discordem dessa opinião na rede, o sistema se mantem neste estado ''ad eternum''. É um sistema bem longe do realista, pois há praticamente 0 risco.&lt;br /&gt;
&lt;br /&gt;
Por último, o sistema composto da opinião 3 é, dentre os 3, o que mais se parece com a realidade. Isso porque, mesmo que de forma desorganizada e sem sentido lógico, os agentes acabam tendo opiniões diferentes, o que resulta em ganhadores e perdedores.&lt;br /&gt;
&lt;br /&gt;
A imagem abaixo mostra as distribuições de retorno para cada um dos 3 casos mencionados:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3 kde.png|350px|thumb|center|Distribuição de retornos para 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enquanto que, para a rede composta apenas de agentes com opinião 1, temos caudas tão pesadas que apresentam sub-picos, na rede composta de opinião 2 a cauda é leve, e basicamente todos os retornos estão situados bem próximos à média da distribuição. Por último, para o caso 3, a cauda é pesada, porém ainda há concentração grande de retornos muito próximos ao centro da distribuição.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4760</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4760"/>
		<updated>2021-05-23T23:28:45Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neste trabalho, o termo &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é tomado como uma constante &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;, e ele é responsável pela indução de ordem ferromagnética local. Em particular, o segundo acomplamento permite casos de ordem ferromagnética local e ordem antiferromagnética global.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4756</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4756"/>
		<updated>2021-05-23T23:13:08Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Simulação de Mercados de Ações */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Por simplicidade, assume-se que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4755</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4755"/>
		<updated>2021-05-23T23:07:50Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i \frac{1}{N} \sum_{j} S_j&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
Considerando um modelo com &amp;lt;math&amp;gt;i = 1,...,N&amp;lt;/math&amp;gt; spins, com as orientações &amp;lt;math&amp;gt;S_i(t) = \pm 1&amp;lt;/math&amp;gt;, a dinâmica dos spins dependerá do campo local &amp;lt;math&amp;gt;h_i(t)&amp;lt;/math&amp;gt;:&lt;br /&gt;
 &amp;lt;math&amp;gt;h_i(t) = \sum_{j} J_{ij} S_j - \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
Por simplicidade, assuma que cada spin é atualizado com uma dinâmica de banho térmico de acordo com:&lt;br /&gt;
 &amp;lt;math&amp;gt;S_i(t+1) = \begin{cases}&lt;br /&gt;
  +1, &amp;amp; \text{com } p = 1/[1 + exp(-2 \beta h_i(t))] \\&lt;br /&gt;
  -1, &amp;amp; \text{com } 1 - p&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*para números muito grandes de agentes, há uma distribuição de retorno de cauda mais leve, o que implica em muito menos situações de alto retorno, um mercado mais estável e consequentemente irreal.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a sua auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis, e portanto não descrevem tão bem um sistema financeiro;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a partir da simulação com 1024 agentes, nota-se a presença de ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil se comparada com um mercado real. Com isto, considera-se que a grade de tamanho 32x32 melhor representa um mercado de ações, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4735</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4735"/>
		<updated>2021-05-23T22:04:05Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Simulação de Mercados de Ações===&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i(t)&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a simulação com 1024 agentes apresenta ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil, não descrevendo muito bem o mercado. Com isto, considera-se que a grade de tamanho 32x32 melhor descreve o mercado, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4732</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4732"/>
		<updated>2021-05-23T22:02:59Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como lei de potências distribuídas dos retornos &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
# O quê os vizinhos fazem: comumente associado à ação de chartistas;&lt;br /&gt;
# O quê a minoria faz: comportamento associado a fundamentalistas, ''traders'' com maior conhecimento sobre valores fundamentais dos mercados de ações.&lt;br /&gt;
&lt;br /&gt;
Neste modelo, essas duas interações conflitantes são combinadas: as interações entre vizinhos são representadas pelo modelo de Ising mais simples; um acoplamento à minoria como um observável global é introduzido por um acoplamento à magnetização global do sistema de spins. Assim, o hamiltoniano incrementado fica com a seguinte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento de cada spin com a magnetização da rede&amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;C_i(t)&amp;lt;/math&amp;gt; representa a estratégia com relação à magnetização da rede.&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a simulação com 1024 agentes apresenta ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil, não descrevendo muito bem o mercado. Com isto, considera-se que a grade de tamanho 32x32 melhor descreve o mercado, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4719</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4719"/>
		<updated>2021-05-23T21:36:17Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
OBJETIVO&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado de ações e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados. Para o caso em que &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt;, os agentes irão adotar estratégias contrárias aos seus vizinhos, e isso também não nos levará a uma representação realista do mercado financeiro. Para que o modelo possa se aproximar da realidade, devemos incrementar o hamiltoniano do sistema.&lt;br /&gt;
&lt;br /&gt;
Um modelo bastante próximo da realidade dos mercados de ações é o proposto por Lux e Marchesi [referências 12 e 13 bornholdt] que classificam os agentes em duas estratégias: os fundamentalistas e os chartistas. Este modelo reproduz muitas das propriedades observadas em mercados reais, como (power-law distribuited returns) &amp;lt;math&amp;gt;ret(t) = ln \left(\frac{p(t)}{p(t-1)} \right)&amp;lt;/math&amp;gt; dos preços &amp;lt;math&amp;gt;p(t)&amp;lt;/math&amp;gt; e uma alta correlação da volatilidade de preços. Além disso, no nível de estratégias, apresenta o fenômeno em que o número de chartistas (ou ''traders'' ruidoso)[talvez tirar essa parte] se correlacionam com fases de grande volatilidade, como visto em mercados reais. Este modelo tem grande sucesso, no entanto sua complexidade é alta. Stefan Bornholdt então propôs um modelo de máxima simplicidade, baseado no modelo de Ising, desenhado para simular a dinâmica de expectativas em sistemas de muitos agentes.&lt;br /&gt;
&lt;br /&gt;
No modelo de Bornholdt, há pelo menos duas forças conflitantes vistas em ações econômicas:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento do spin com a magnetização da rede toda &amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;C_i(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos &amp;lt;ref name='ret'&amp;gt;[http://www.portalaction.com.br/series-temporais/51-retornos Retornos. Portal Action.]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos &amp;lt;ref name='kde'&amp;gt;[https://en.wikipedia.org/wiki/Kernel_density_estimation Kernel Density Estimation. Wikipedia]&amp;lt;/ref&amp;gt;===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|500px|thumb|right|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura ao lado.&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin &amp;lt;ref name='wiener1'&amp;gt;[https://mathworld.wolfram.com/Wiener-KhinchinTheorem.html Wiener-Khinchin Theorem. Wolfram Math World]&amp;lt;/ref&amp;gt; &amp;lt;ref name='wiener2'&amp;gt;[https://en.wikipedia.org/wiki/Wiener%E2%80%93Khinchin_theorem Wiener–Khinchin theorem. Wikipedia]&amp;lt;/ref&amp;gt; foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
&lt;br /&gt;
Um dos objetivos deste estudo é verificar qual o tamanho de grade gera um resultado que melhor simula um índice financeiro. A escolha de índices financeiros para comparação, ao invés de ações ou commodities, é por causa da instabilidade que ativos financeiros separados têm. Imaginando um cenário fictício onde uma empresa A vende sorvetes enquanto a empresa B vende chocolate quente. A tendência é que haja uma sazonalidade nos 2 ativos, de tal forma que, no verão, as ações de A subam enquanto B desce, e vice-versa no inverno. Porém, enquanto os 2 ativos estão se movimentando, o movimento do mercado representado por estas 2 ações permanece aproximadamente constante. Como índices financeiros são, na verdade, médias de um conjunto grande e diverso de ações presentes no mercado, são melhores para a comparação com o modelo.&lt;br /&gt;
&lt;br /&gt;
Foram escolhidos 4 diferentes tamanhos de grade:&lt;br /&gt;
&lt;br /&gt;
*16x16: 256 agentes&lt;br /&gt;
*32x32: 1024 agentes&lt;br /&gt;
*50x50: 2500 agentes&lt;br /&gt;
*100x100: 10000 agentes&lt;br /&gt;
&lt;br /&gt;
Cada uma das simulações se deu sob as seguintes condições:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;J = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;T = 1,5 &amp;lt;/math&amp;gt;&lt;br /&gt;
*Todos os agentes são racionais, ou seja, eles podem trocar de opinião ao longo da simulação, assumindo &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt; em alguns momentos e &amp;lt;math&amp;gt;C_i = 1&amp;lt;/math&amp;gt; em outros, de acordo com o grupo que o agente está inserido: maioria ou minoria.&lt;br /&gt;
&lt;br /&gt;
Abaixo é possível observar fotografias do sistema em diferentes instantes para cada uma das simulações:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:N16.png|250px|thumb|center|Situação do sistema de 256 agentes (grade 16 x 16) em 9 instantes diferentes.     ]] &lt;br /&gt;
! [[Arquivo:N32.png|250px|thumb|center|Situação do sistema de 1024 agentes (grade 32 x 32) em 9 instantes diferentes.    ]] &lt;br /&gt;
! [[Arquivo:N50.png|250px|thumb|center|Situação do sistema de 2500 agentes (grade 50 x 50) em 9 instantes diferentes.    ]]&lt;br /&gt;
! [[Arquivo:N100.jpg|250px|thumb|center|Situação do sistema de 10000 agentes (grade 100 x 100) em 9 instantes diferentes.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Como saída da simulação é obtida uma série temporal dos valores de magnetização, que neste modelo significam o preço de um ativo presente no mercado. Utilizando a série de preços (magnetização), foi obtido, então, a série dos retornos logarítmicos normalizados, através do método explicado na seção dos [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Retornos|Retornos]]. Para comparar o modelo com dados reais, obteve-se as series temporais do preço de índices do mercado financeiro: Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ. Esses dados foram obtidos com a biblioteca [https://pandas-datareader.readthedocs.io/en/latest/ ''Pandas Datareader''] do Python, que permite obter dados de páginas da internet como a [https://finance.yahoo.com/ ''Yahoo Finance''], que possui a série temporal dos preços de vários ativos financeiros. Assim como nas simulações, a partir da série de preços dos índices foram calculadas a série temporal dos retornos logarítmicos normalizados.&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo pode-se observar os retornos de cada simulação e índice financeiro:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|600px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
Alguns pontos interessantes a se observar:&lt;br /&gt;
&lt;br /&gt;
*os retornos dos índices S&amp;amp;P 500, Dow Jones e NASDAQ são muito parecidos, isso de deve ao fato de que todos são índices de mercados dos Estados Unidos, enquanto o Ibovespa é um índice de mercado brasileiro;&lt;br /&gt;
*os retornos das simulações vão variando mais tempo perto do zero conforme o número de agentes cresce;&lt;br /&gt;
*conforme o número de agentes no sistema aumenta, diminui-se o número de transições agudas de retorno, representadas pelos picos no gráfico. Isso indica um mercado mais estável.&lt;br /&gt;
*o objeto da simulação não é retornar uma cópia do observado nos dados reais, mas sim um cenário parecido. O intuito é criar um novo mercado, artificial, com características parecidas ao observado nos mercados reais.&lt;br /&gt;
&lt;br /&gt;
Para ter uma comparação melhor a fim de entender que tamanho de grade simula melhor um mercado financeiro, é importante ver a [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|distribuição dos retornos]] e a auto correlação das [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidades]]. Com base no conteúdo da seção [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Distribui.C3.A7.C3.A3o_dos_Retornos_.5B2.5D|Distribuição dos Retornos]] foi gerado uma curva de densidade de probabilidade para cada série de retorno, que podem ser observadas na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|600px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
Desta figura pode-se também observar alguns pontos:&lt;br /&gt;
&lt;br /&gt;
*quanto maior o número de agentes, mais longe a distribuição dos retornos das simulações ficam da distribuição dos retornos dos índices de mercado;&lt;br /&gt;
*as caudas das distribuições dos retornos das simulações vão ficando mais pesadas conforme o número de agentes diminui, o que indica mais uma vez que as simulações com menor número de agentes possuem distribuição dos retornos mais parecidas com a do mercado financeiro, que também possui uma cauda pesada;&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo estão presentes as auto correlações dos retornos quadrados, ou seja, da [[Modelo_de_Bornholdt_para_simulação_de_mercados_financeiros_artificiais#Volatilidade|volatilidade]] dos retornos:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Volatilidade.png|600px|thumb|center|Auto correlação das volatilidades dos retornos das simulações (primeira coluna) e do retorno dos índices financeiros (segunda coluna). Em ambas as colunas, a escala dos eixos y e x dos gráficos é logarítmica.]]&lt;br /&gt;
&lt;br /&gt;
Desta imagem são notados alguns aspectos como:&lt;br /&gt;
&lt;br /&gt;
*o comportamento da auto correlação das volatilidades das simulações com mais agentes são mais parecidas com as dos índices financeiros;&lt;br /&gt;
*embora a simulação com 256 agentes tenha a distribuição dos retornos que mais se aproximou, analisando a auto correlação da volatilidade se observa que para este número de agentes os retornos são muito voláteis;&lt;br /&gt;
*mesmo que as simulações com maior número de agentes apresente a auto correlação das volatilidades mais similar as do mercado financeiro, a simulação com 1024 agentes apresenta ''clusters'' de volatilidade, comprovando o fato estilizado de que existe memória do retorno quadrado.&lt;br /&gt;
&lt;br /&gt;
Considerando os pontos apresentados, percebe-se que grades de um tamanho grande não descrevem o mercado financeiro da melhor forma, e da mesma forma, mesmo que aparente descrever bem devido a distribuição de retornos semelhantes a do mercado financeiro, a simulação de 256 agentes é muito volátil, não descrevendo muito bem o mercado. Com isto, considera-se que a grade de tamanho 32x32 melhor descreve o mercado, pois possui uma distribuição dos retornos que não difere tanto da distribuição dos retornos dos índices financeiros, e ainda apresenta o fato estilizado da memória da volatilidade.&lt;br /&gt;
&lt;br /&gt;
===Variação da opinião dos agentes===&lt;br /&gt;
&lt;br /&gt;
O parâmetro &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, como dito anteriormente, indica a opinião de um agente &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; presente na rede. Esta opinião está relacionada a seguir (ou não) o comportamento da maioria dos outros agentes presentes no sistema.&lt;br /&gt;
&lt;br /&gt;
Por consequência, pode-se resumir as possíveis opiniões que um agente tem na rede em 3 ramos diferentes:&lt;br /&gt;
&lt;br /&gt;
*Opinião 1: &amp;lt;math&amp;gt;C_i = +1&amp;lt;/math&amp;gt;. Agente que opõe sua opinião à da maioria dos outros agentes no sistema, chamado de '''fundamentalista'''. Recebem este nome pois se apoiam no princípio fundamental de oferta e demanda da economia, o qual diz que, com demanda maior, a oferta é menor, enquanto que para demandas menores, a oferta é maior. Logo, opinando diferente da maioria, garante-se um maior retorno.&lt;br /&gt;
*Opinião 2: &amp;lt;math&amp;gt;C_i = -1&amp;lt;/math&amp;gt;. Agente que iguala sua opinião à da maioria dos outros agentes no sistema, chamado de '''chartista'''. Recebe este nome do termo em inglês ''chart'' (gráfico). São agentes que sempre analisam, através de gráficos, as ações em alta, para comprá-las, e as em baixa, para vendê-las. Por isso, seguem a maioria do sistema.&lt;br /&gt;
*Opinião 3: &amp;lt;math&amp;gt;C_i = c \in \{-1;+1\}&amp;lt;/math&amp;gt;. Agente que não possui estratégia, e a cada passo da simulação joga aleatoriamente do lado dos chartistas ou fundamentalistas, sem raciocínio. É chamado de '''completamente irracional'''.&lt;br /&gt;
&lt;br /&gt;
Abaixo, estão gráficos que mostram o comportamento do sistema composto inteiramente por cada tipo de opinião considerada na rede.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! [[Arquivo:Opinion1.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 1]] &lt;br /&gt;
! [[Arquivo:Opinion2.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 2]] &lt;br /&gt;
! [[Arquivo:Opinion3.png|350px|thumb|center|Simulação com 100% da rede contendo agentes de Opinião 3]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Para o sistema composto apenas pela opinião 1, nota-se uma volatilidade muito grande na série temporal. Como os agentes de opinião 1 sempre jogam contra a maioria, quando o sistema atinge um estado de preços grande o suficiente, por exemplo, ocorre uma &amp;quot;debandada&amp;quot; dos agentes, que passam a opinar contra. Desta forma, o preço abaixa rapidamente, até chegar num estado suficientemente baixo, onde os agentes passam a opinar a favor.&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
===Código para obter a série temporal do preço dos índices financeiros===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pandas_datareader as pdr&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
&lt;br /&gt;
ibov = pdr.get_data_yahoo(symbols='^BVSP',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
SP500 =  pdr.get_data_yahoo(symbols='^GSPC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
DJ = pdr.get_data_yahoo(symbols='^DJI',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
Nasdaq = pdr.get_data_yahoo(symbols='^IXIC',start=datetime(1995,1,1),end=datetime(2021,1,1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular os retornos e para os normalizar===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def ret(x):&lt;br /&gt;
    N = len(x)&lt;br /&gt;
&lt;br /&gt;
    y = []&lt;br /&gt;
    for i in range(N-1):&lt;br /&gt;
        r = np.log(x[i+1])-np.log(x[i])&lt;br /&gt;
        y.append(r)&lt;br /&gt;
&lt;br /&gt;
    return y&lt;br /&gt;
&lt;br /&gt;
def normalize(x):&lt;br /&gt;
    &lt;br /&gt;
    N = len(x)    &lt;br /&gt;
    y = []&lt;br /&gt;
    &lt;br /&gt;
    for i in range(N):&lt;br /&gt;
        n = x[i] - np.mean(x)&lt;br /&gt;
        n = n/np.std(x)&lt;br /&gt;
        &lt;br /&gt;
        y.append(n)&lt;br /&gt;
        &lt;br /&gt;
    return np.array(y)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código que realiza a estimativa de densidade ''kernel''===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def gauss(x,mean,std_dev):&lt;br /&gt;
    u = (x - mean) / std_dev&lt;br /&gt;
    c = 1 / (np.sqrt(2 * np.pi))&lt;br /&gt;
    return c * np.exp(- 0.5 * u ** 2)&lt;br /&gt;
&lt;br /&gt;
def kde(x,kernel=&amp;quot;gauss&amp;quot;,bw=0.1,n_points=1500):&lt;br /&gt;
    kernel_options = [&amp;quot;gauss&amp;quot;]&lt;br /&gt;
    data = np.array(x)&lt;br /&gt;
    x_kde = np.linspace(np.min(data)-bw,np.max(data)+bw,n_points)&lt;br /&gt;
    n = data.shape[0]     #Number of rows&lt;br /&gt;
    m = x_kde.shape[0]    #Number of columns&lt;br /&gt;
    kde_i = []&lt;br /&gt;
    if kernel == kernel_options[0]:&lt;br /&gt;
        for x in data:&lt;br /&gt;
            kde_i.append(gauss(x_kde,x,bw))&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Kernel not found!&amp;quot;)&lt;br /&gt;
        print(&amp;quot;Kernel options are:&amp;quot;)&lt;br /&gt;
        for k in kernel_options:&lt;br /&gt;
            print(&amp;quot; - &amp;quot; + k)&lt;br /&gt;
        return np.nan&lt;br /&gt;
          &lt;br /&gt;
    kde_i = np.array(kde_i).reshape(n,m)&lt;br /&gt;
    &lt;br /&gt;
    kde = np.array([np.sum(kde_i[:,i]) for i in np.arange(m)])&lt;br /&gt;
    kde_norm = kde / np.sum(kde)&lt;br /&gt;
    return x_kde,kde_norm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para calcular a auto correlação das volatilidades===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.signal import get_window&lt;br /&gt;
from scipy.fft import rfft, rfftfreq, irfft&lt;br /&gt;
&lt;br /&gt;
def fft_calculation(y,window=&amp;quot;parzen&amp;quot;):&lt;br /&gt;
    w = get_window(window=window, Nx=len(y))&lt;br /&gt;
    f = y * w&lt;br /&gt;
    freqs = np.fft.rfftfreq(len(y))&lt;br /&gt;
    return freqs,np.abs(rfft(f))&lt;br /&gt;
&lt;br /&gt;
def autocorr_calculation(y):&lt;br /&gt;
    ift = irfft(np.abs(y) ** 2)&lt;br /&gt;
    ift_norm = np.abs(ift) / np.abs(ift).max()&lt;br /&gt;
    return ift_norm&lt;br /&gt;
&lt;br /&gt;
w_ibov, s_ibov = fft_calculation(np.array(normalize(r_ibov))**2)&lt;br /&gt;
c_ibov = autocorr_calculation(s_ibov)&lt;br /&gt;
&lt;br /&gt;
w_sp500, s_sp500 = fft_calculation(np.array(normalize(r_SP500))**2)&lt;br /&gt;
c_sp500 = autocorr_calculation(s_sp500)&lt;br /&gt;
&lt;br /&gt;
w_DJ, s_DJ = fft_calculation(np.array(normalize(r_DJ))**2)&lt;br /&gt;
c_DJ = autocorr_calculation(s_DJ)&lt;br /&gt;
&lt;br /&gt;
w_nasdaq, s_nasdaq = fft_calculation(np.array(normalize(r_nasdaq))**2)&lt;br /&gt;
c_nasdaq = autocorr_calculation(s_nasdaq)&lt;br /&gt;
&lt;br /&gt;
w100, s100 = fft_calculation(np.array(normalize(R100))**2)&lt;br /&gt;
c100 = autocorr_calculation(s100)&lt;br /&gt;
&lt;br /&gt;
w50, s50 = fft_calculation(np.array(normalize(R50))**2)&lt;br /&gt;
c50 = autocorr_calculation(s50)&lt;br /&gt;
&lt;br /&gt;
w32, s32 = fft_calculation(np.array(normalize(R32))**2)&lt;br /&gt;
c32 = autocorr_calculation(s32)&lt;br /&gt;
&lt;br /&gt;
w16, s16 = fft_calculation(np.array(normalize(R16))**2)&lt;br /&gt;
c16 = autocorr_calculation(s16)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(np.arange(len(R16)),R16,'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(np.arange(len(R32)),R32,'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(np.arange(len(R50)),R50,'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(np.arange(len(R100)),R100,'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(np.arange(len(r_ibov)),normalize(r_ibov),'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(np.arange(len(r_SP500)),normalize(r_SP500),'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(np.arange(len(r_DJ)),normalize(r_DJ),'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(np.arange(len(r_nasdaq)),normalize(r_nasdaq),'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
&lt;br /&gt;
fig.suptitle('Retornos(t)',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, 't', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Índices', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, 'r(t)', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='upper left')&lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da distribuição dos retornos===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
y100 = np.array(R100)&lt;br /&gt;
y50 = np.array(R50)&lt;br /&gt;
y32 = np.array(R32)&lt;br /&gt;
y16 = np.array(R16)&lt;br /&gt;
&lt;br /&gt;
kde100 = kde(y100,&amp;quot;gauss&amp;quot;,np.std(y100)/3,1500)&lt;br /&gt;
kde50 = kde(y50,&amp;quot;gauss&amp;quot;,np.std(y50)/3,1500)&lt;br /&gt;
kde32 = kde(y32,&amp;quot;gauss&amp;quot;,np.std(y32)/3,1500)&lt;br /&gt;
kde16 = kde(y16,&amp;quot;gauss&amp;quot;,np.std(y16)/3,1500)&lt;br /&gt;
&lt;br /&gt;
y_ibov = np.array(normalize(r_ibov))&lt;br /&gt;
y_sp500 = np.array(normalize(r_SP500))&lt;br /&gt;
y_dj = np.array(normalize(r_DJ))&lt;br /&gt;
y_nasdaq = np.array(normalize(r_nasdaq))&lt;br /&gt;
&lt;br /&gt;
kde_ibov = kde(y_ibov,&amp;quot;gauss&amp;quot;,np.std(y_ibov)/3,1500)&lt;br /&gt;
kde_sp500= kde(y_sp500,&amp;quot;gauss&amp;quot;,np.std(y_sp500)/3,1500)&lt;br /&gt;
kde_dj = kde(y_dj,&amp;quot;gauss&amp;quot;,np.std(y_dj)/3,1500)&lt;br /&gt;
kde_nasdaq = kde(y_nasdaq,&amp;quot;gauss&amp;quot;,np.std(y_nasdaq)/3,1500)&lt;br /&gt;
&lt;br /&gt;
fig, ax = plt.subplots(figsize=(10,6))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlabel('Retorno normalizado',fontsize=12)&lt;br /&gt;
ax.set_ylabel('Densidade de probabilidade',fontsize=12)&lt;br /&gt;
fig.suptitle('Distribuição do retorno (normalizado)',fontsize=14)&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde100[0],kde100[1],label='# agentes 10000')&lt;br /&gt;
plt.plot(kde50[0],kde50[1],label='# agentes 2500')&lt;br /&gt;
plt.plot(kde32[0],kde32[1],label='# agentes 1024')&lt;br /&gt;
plt.plot(kde16[0],kde16[1],label='16')&lt;br /&gt;
&lt;br /&gt;
plt.plot(kde_ibov[0],kde_ibov[1],'--',label='Ibovespa')&lt;br /&gt;
plt.plot(kde_sp500[0],kde_sp500[1],'--', label='S&amp;amp;P500')&lt;br /&gt;
plt.plot(kde_dj[0],kde_dj[1],'--', label='Dow Jones')&lt;br /&gt;
plt.plot(kde_nasdaq[0],kde_nasdaq[1],'--', label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ax.set_xlim(-3,3)&lt;br /&gt;
plt.legend()&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Código para gerar a figura da auto correlação das volatilidades===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
fig, ax = plt.subplots(4,2,figsize=(10,7))&lt;br /&gt;
&lt;br /&gt;
ax[0][0].plot(c16[:int(len(c16)/2)],'lightsteelblue',label='# agentes = 256')&lt;br /&gt;
ax[1][0].plot(c32[:int(len(c32)/2)],'cornflowerblue',label='# agentes = 1024')&lt;br /&gt;
ax[2][0].plot(c50[:int(len(c50)/2)],'blue',label='# agentes = 2500')&lt;br /&gt;
ax[3][0].plot(c100[:int(len(c100)/2)],'midnightblue',label='# agentes = 10000')&lt;br /&gt;
&lt;br /&gt;
ax[0][1].plot(c_ibov[:int(len(c_ibov)/2)],'pink',label='Ibovespa')&lt;br /&gt;
ax[1][1].plot(c_sp500[:int(len(c_sp500)/2)],'palevioletred',label='S&amp;amp;P500')&lt;br /&gt;
ax[2][1].plot(c_DJ[:int(len(c_DJ)/2)],'mediumvioletred',label='Dow Jones')&lt;br /&gt;
ax[3][1].plot(c_nasdaq[:int(len(c_nasdaq)/2)],'purple',label='NASDAQ')&lt;br /&gt;
&lt;br /&gt;
# Setting labels &amp;amp; titles&lt;br /&gt;
#ax[2].set_xlabel('Data',fontsize=12)&lt;br /&gt;
#ax[1].set_ylabel('Retorno',fontsize=12)&lt;br /&gt;
fig.suptitle('Autocorrelação das volatilidades',fontsize=14)&lt;br /&gt;
fig.text(0.5,0, '$\\tau$', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.28,0.93, 'Bornholdt', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0.77,0.93, 'Indíces', ha='center', fontsize=12)&lt;br /&gt;
fig.text(0, 0.5, '$A(\\tau)$', va='center', rotation='vertical',fontsize=12)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for aa in ax: &lt;br /&gt;
    for a in aa:&lt;br /&gt;
        a.xaxis.set_major_locator(plt.MaxNLocator(8))&lt;br /&gt;
        a.yaxis.set_major_locator(plt.MaxNLocator(5))&lt;br /&gt;
        a.legend(loc='lower left')&lt;br /&gt;
        a.set_yscale('log')&lt;br /&gt;
        a.set_xscale('log')&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
fig.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4568</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4568"/>
		<updated>2021-05-22T18:50:47Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples, que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado financeiro e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados.&lt;br /&gt;
&lt;br /&gt;
O Modelo de Bornholdt, se incluid {coisas do artigo}. Assim, o hamiltoniano do sistema fica complementado:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i S_j - \sum_{i} \alpha C_i(t) \frac{1}{N} \sum_{j} S_j(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é o termo de acomplamento do spin com a rede toda &amp;lt;math&amp;gt;(\alpha &amp;gt; 0)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|700px|thumb|center|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
Em Julia, 8000 passos de MC&lt;br /&gt;
16x16: 0.512 s&lt;br /&gt;
32x32: 2.332 s&lt;br /&gt;
50x50: 10.674 s&lt;br /&gt;
100x100: 154.134 s&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|700px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|700px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4567</id>
		<title>Modelo de Bornholdt para simulação de mercados financeiros artificiais</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Bornholdt_para_simula%C3%A7%C3%A3o_de_mercados_financeiros_artificiais&amp;diff=4567"/>
		<updated>2021-05-22T18:33:39Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelo de Bornholdt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
==Modelo de Bornholdt==&lt;br /&gt;
Para estudar os fenômenos físicos que nos rodeiam, usamos modelos matemáticos para entender como sistemas evoluem com o tempo. No entanto, esses modelos muitas vezes podem ser base para estudos além do sistema físico de interesse. Para um sistema de spins, um dos modelos mais simples, que leva em conta apenas a interação de cada spin com seus primeiros vizinhos, é o Modelo de Ising. O hamiltoniano que o descreve é defindo pela segunte expressão:&lt;br /&gt;
 &amp;lt;math&amp;gt;\mathcal{H} = \sum_{\langle i, j \rangle} J_{ij} S_i^z S_j^z&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;J_{ij}&amp;lt;/math&amp;gt; é o termo que define a força de interação entre os spins '''i''' e '''j''' e &amp;lt;math&amp;gt;S^z&amp;lt;/math&amp;gt; a componente Z do spin. Além disso &amp;lt;math&amp;gt;\langle i, j \rangle&amp;lt;/math&amp;gt; denota que estamos somando somente sobre os primeiros vizinhos. Para um valor de &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, a interação ferromagnética é favorecida, e os spins vizinhos tendem a se alinhar conjuntamente, formando domínios magnéticos. No entanto, para &amp;lt;math&amp;gt;J_{ij} &amp;lt; 0&amp;lt;/math&amp;gt; a interação antiferromagnética é favorecida, e os spins tende a se &amp;quot;anti-alinhar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Podemos fazer um paralelo interessante entre os spins e a sua interação com seus vizinhos com ''traders'' em mercados finaceiros e a suas interações com outros ''traders''. No caso do Modelo de Ising, podemos interpretar cada spin como um ''trader'', ou agente, em um mercado financeiro e a direção da componente Z desse spin como a sua estratégia de compra ou venda. Então neste caso mais simples, para &amp;lt;math&amp;gt;J_{ij} &amp;gt; 0&amp;lt;/math&amp;gt;, os agentes tenderão a adotar a mesma estratégia de mercado, e isso não descreve bem a realidade dos mercados.&lt;br /&gt;
&lt;br /&gt;
==Alguns conceitos importantes==&lt;br /&gt;
&lt;br /&gt;
===Retornos===&lt;br /&gt;
&lt;br /&gt;
Quando se trata de sistemas financeiros, os estudos se concentram mais no retorno dos ativos do que no preço em si, pois a série temporal dos retornos tem propriedades estatísticas mais interessantes que a série dos preços.&lt;br /&gt;
&lt;br /&gt;
Sendo ''P(t)'' o preço de um ativo financeiro no instante ''t'', e ''P(t-1)'' o preço do ativo no instante ''(t-1)'', o retorno linear do ativo é:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = \frac{P(t) - P(t-1)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reescrevendo esta equação, obtemos que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) + 1= \frac{P(t)}{P(t-1)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aplicando a função logarítmica em ambos os lados da equação, e considerando que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;ln(x + 1) \approx x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
obtêm-se o retorno logarítmico, que é mais indicado quando se têm ativos voláteis, que possuem uma variação muito alta:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;r(t) = ln\left(\frac{P(t)}{P(t-1)}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Considerando que neste estudo serão comparados retornos de diferentes índices, e também os retornos obtidos através das simulações com o modelo de Bornholdt, é importante normalizar os retornos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;\bar{r}_n = \frac{r_n  - \langle r \rangle}{\sigma_r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\sigma_r&amp;lt;/math&amp;gt; é o desvio padrão da serie de retornos e &amp;lt;math&amp;gt;\langle r \rangle&amp;lt;/math&amp;gt; a média.&lt;br /&gt;
&lt;br /&gt;
===Distribuição dos Retornos===&lt;br /&gt;
Quando se tem um volume considerável de dados é possível obter a distribuição probabilística deles. Para isso pode-se utilizar a estimação de densidade de Kernel (KDE). Ao observar uma pequena janela de tamanho ''h'' em torno de um ponto em análise, pode-se dizer que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;P(x-h \leq x \leq x+h ) \approx \frac{1}{N}\sum_n^N W(u) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sendo &amp;lt;math&amp;gt;W(u)&amp;lt;/math&amp;gt; uma função ''kernel'' e &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; uma variável tal que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;u = \frac{x - x_n}{2h}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para este estudo utilizou-se um ''kernel'' gaussiano:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;W(u) = \frac{1}{\sqrt{2\pi}} e^{-\frac{1}{2}u^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Este método foi aplicado para as séries de retorno para obter a distribuição deles, utilizando &amp;lt;math&amp;gt;h = 0.5 \sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Volatilidade===&lt;br /&gt;
&lt;br /&gt;
Uma forma de calcular a volatilidade da série temporal de retornos ao longo do tempo é elevar ao quadrado os valores da série. Deste modo pode-se obter uma variável como a que está ilustrada na figura abaixo:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Exemplo volatilidade.png|700px|thumb|center|Exemplo de uso da volatilidade como série temporal de um retorno arbitrário.]]&lt;br /&gt;
&lt;br /&gt;
O interessante em estudar volatilidade de retornos financeiros é que essa variável reflete o quão ''imprevisível'' é um determinado ativo. Uma ação com alta volatilidade tende a ter um risco maior de investimento, ao passo que ações com baixa volatilidade geralmente retornam riscos menores, pois seu comportamento acaba sendo mais previsível.&lt;br /&gt;
&lt;br /&gt;
Um fato estilizado financeiro é que a volatilidade das séries temporais de retorno apresentam comportamento sazonal por natureza. Há períodos de alta volatilidade, seguidos por períodos com baixa volatilidade, que então são novamente seguidos por alta volatilidade, e assim adiante. E uma forma de mensurar isto é verificando a presença de ''clusters'' de autocorrelação na volatilidade de retornos. Isto é, através da análise da autocorrelação da volatilidade, encontrar bolhas que indiquem as fases destes comportamentos. &lt;br /&gt;
&lt;br /&gt;
Para obter a auto correlação o Teorema de Wiener-Khinchin foi utilizado, de forma que:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;A(\tau) =\mathcal{F}\{|S(\omega)|^2\}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;S(\omega)&amp;lt;/math&amp;gt; é a transformada de Fourier do quadrado dos retornos.&lt;br /&gt;
&lt;br /&gt;
==Simulações==&lt;br /&gt;
===Variação do tamanho da grade===&lt;br /&gt;
Em Julia, 8000 passos de MC&lt;br /&gt;
16x16: 0.512 s&lt;br /&gt;
32x32: 2.332 s&lt;br /&gt;
50x50: 10.674 s&lt;br /&gt;
100x100: 154.134 s&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Retornos.png|700px|thumb|center|Retornos logarítmicos normalizados obtidos para as simulações com diferentes números de agentes (tamanho da grade) na primeira coluna, e na segunda coluna os retornos logarítmicos normalizados para os índices financeiros Ibovespa, S&amp;amp;P 500, Dow Jones e NASDAQ]]&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Dist.png|700px|thumb|center|Distribuição dos retornos das simulações (linha cheia) e dos índices financeiros (linha tracejada). Percebe-se que a distribuição dos retornos das simulações que mais se aproximam da distribuição dos índices financeiros são as que possuem um menor número de agentes.]]&lt;br /&gt;
&lt;br /&gt;
==Conclusões==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4024</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4024"/>
		<updated>2021-04-06T00:44:38Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar e estudar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de formato gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.zeros((parametros.N_y, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Código completo se encontra no Github.'''''&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4023</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4023"/>
		<updated>2021-04-06T00:40:06Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar e estudar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de formato gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.zeros((parametros.N_y, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4022</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4022"/>
		<updated>2021-04-06T00:38:59Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar e estudar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de formato gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.full((parametros.N_y, parametros.N_y), 1 / (L ** 2)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4021</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=4021"/>
		<updated>2021-04-06T00:34:48Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de explorar e estudar a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como um anel, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de formato gaussiano sob a malha. Por isso, é interessante analisar a solução estacionária (se existir).&lt;br /&gt;
&lt;br /&gt;
Como as equações diferenciais do sistema são dependentes umas das outras (isto é, a equação de m(x,t) depende de p(x,t) e a de p depende de m), a solução não é trivial. Utilizando o Método de Coeficientes a Determinar para solução de equações diferenciais em estado estacionário, conseguimos a seguinte relação genérica, que se mostra útil:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; m(x,t) = A_1 e^{- B_1 x^2} + A_2 p(x,t) + A_3 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Onde &amp;lt;math&amp;gt;A_1,A_2,A_3&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;B_1&amp;lt;/math&amp;gt; são constantes que dependem das condições iniciais do problema. Como o objetivo do trabalho não é resolver analiticamente esta EDP, estas constantes não foram calculadas.&lt;br /&gt;
&lt;br /&gt;
Mas a equação acima mostra que, para o estado estacionário, o formato gaussiano obtido era previsto na solução analítica também. Portanto, o resultado obtido apresenta coerência.&lt;br /&gt;
&lt;br /&gt;
Mais um ponto a ser aferido é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Um cuidado importante na iniciação deste sistema é que, como estamos modelando a densidade populacional, e consideramos que não há perda de população com o tempo, a integral da função p(x,t) deve ser sempre igual a 1. Em t=0, na iniciação do sistema, é necessário implementar esta condição ao problema, para que ela se mantenha durante a simulação. Para isso, basta sortear valores e normalizá-los depois. Um exemplo de código simples em Python que realiza esta operação está indicado abaixo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
N = 100   #Limite no eixo x&lt;br /&gt;
p_auxiliar = np.random.rand(N)   #Vetor auxiliar&lt;br /&gt;
p = p_auxiliar / np.sum(p_auxiliar)   #Normalização, para que a soma de p em todo x seja 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se notar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao estacionário, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais uma vez, como iniciamos aleatoriamente a população, é importante normalizá-la para que a integral seja igual a 1, como dito acima.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial aleatório do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de formato gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para a geração da evolução do sistema e do gif, o código utilizado foi o seguinte:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
L = 100 # Tamanho do Grid&lt;br /&gt;
D_p = 0.5 # Coeficiente de difusão de pessoas&lt;br /&gt;
D_m = 0.5 # Coeficiente de difusão de dinheiro&lt;br /&gt;
ds = 1 # Diferencial Espacial&lt;br /&gt;
dt = 0.3 # Diferencial Temporal&lt;br /&gt;
alfa = 1.2 # Taxa de produção de economia per capita&lt;br /&gt;
beta = 0.03 # Taxa de decaimente da economia&lt;br /&gt;
gamma = 1 # Taxa de velocidade com que as pessoas migram em direção ao dinheiro&lt;br /&gt;
&lt;br /&gt;
# CRIA OBJETO DE PARÂMETROS PARA O MODELO #&lt;br /&gt;
parametros = ParametrosKellerSegelModel(L, L, D_p, D_m, ds, dt, alfa, beta, gamma)&lt;br /&gt;
&lt;br /&gt;
# INICIALIZA O MODELO COM OS PARÂMETROS #&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# GERA CONDIÇÕES INICIAIS A SEREM ESTUDADAS #&lt;br /&gt;
condicao_inicial_populacao = np.matrix(np.full((parametros.N_x, parametros.N_x), 1 / (L ** 2)))&lt;br /&gt;
condicao_inicial_dinheiro = np.matrix(np.full((parametros.N_y, parametros.N_y), 1 / (L ** 2)))&lt;br /&gt;
&lt;br /&gt;
condicao_inicial_dinheiro[(0, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(0, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 99)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(99, 0)] = 0.125&lt;br /&gt;
condicao_inicial_dinheiro[(49, 49)] = 2&lt;br /&gt;
condicao_inicial_dinheiro[(49, 69)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(49, 29)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(69, 49)] = 1&lt;br /&gt;
condicao_inicial_dinheiro[(29, 49)] = 1&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE GRÁFICO ESTÁTICO&lt;br /&gt;
jpeg = JpegTool(nome_imagem = 'comparacao_tempos_pop_uniforme_sem_dinheiro')&lt;br /&gt;
&lt;br /&gt;
# GERA GRÁFICOS&lt;br /&gt;
jpeg.geraJpeg(modelo)&lt;br /&gt;
&lt;br /&gt;
# REINICIALIZA MODELO&lt;br /&gt;
modelo = KellerSegelModel(parametros)&lt;br /&gt;
&lt;br /&gt;
# SETA AS CONDIÇÕES INICIAIS DO MODELO #&lt;br /&gt;
modelo.setEstadoInicial(condicao_inicial_populacao, condicao_inicial_dinheiro)&lt;br /&gt;
&lt;br /&gt;
# GERA O OBJETO DE ANIMACAO #&lt;br /&gt;
ani = AnimacaoTool(nome_gif = 'dinamica_pop_eco_2d_pop_uniforme_sem_dinheiro')&lt;br /&gt;
&lt;br /&gt;
# GERA GIF COM A EVOLUCAO DO MODELO #&lt;br /&gt;
ani.geraGif(modelo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3893</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3893"/>
		<updated>2021-04-04T03:52:17Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel &amp;lt;ref name='keller-segel-original'&amp;gt;Evelyn F. Keller, Lee A. Segel, Initiation of slime mold aggregation viewed as an instability, Journal of Theoretical Biology, Volume 26, Issue 3, 1970, Pages 399-415&amp;lt;/ref&amp;gt;, que originalmente descreve o movimento de células em direção a um sinal químico, para um sistema englobando população e atividade econômica, problema proposto no livro ''Introduction to the Modeling and Analysis of Complex Sistems '' de Hiroki Sayama &amp;lt;ref name='sayama'&amp;gt;Sayama, H. Introduction to the Modeling and Analysis of Complex Systems. 2015&amp;lt;/ref&amp;gt;. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space''), método de resolução de equações diferenciais parciais, como a equação do calor e a da difusão, que é o caso deste trabalho.&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel== &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'', a taxa com que as células se movem em direção ao sinal químico, tem papel crítico na auto-organização das células. &amp;lt;ref name = 'thesis'&amp;gt; Hoffmann, F. C. O. Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis , Tese de doutorado. 2017 [https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas &amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica&amp;lt;ref name='sayama'&amp;gt;&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
O trabalho agora é traduzir essas premissas em equações. O primeiro ponto diz que que padrão não há mudança na população, dessa forma:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O segundo ponto nos diz que a economia tem um aumento que depende da quantidade de pessoas, e assim:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a taxa de aumento da atividade econômica per capita.&lt;br /&gt;
&lt;br /&gt;
O terceiro ponto diz que a atividade econômica decai quando não há pessoas, e para isso adicionamos um termo de decaimento na equação:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = \alpha p  - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
em que &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a taxa de decaimento da atividade econômica. &lt;br /&gt;
 &lt;br /&gt;
O quarto ponto fala que tanto população quanto a atividade econômica difundem, o que uma premissa sobre o movimento espacial. Para isso são adicionados termos de difusão, os Laplacianos, as equações:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da atividade econômica respectivamente.&lt;br /&gt;
&lt;br /&gt;
O quinto e último ponto fala que as pessoas são atraídas pela atividade econômica e assim se movem para áreas que possuem mais dinheiro. Para cumprir essa premissa, a equação do transporte é utilizada:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
 -  \nabla \cdot (p \gamma \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que o gradiente de &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; é utilizado para obter a velocidade média do movimento da população, sendo &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; uma constante que afeta essa velocidade. &lt;br /&gt;
&lt;br /&gt;
O sistema de equação final fica da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos, &amp;lt;ref name='scherer'&amp;gt;Scherer, C. Métodos Computacionais da Física. 2010&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial caótico do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de shape gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3450</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3450"/>
		<updated>2021-03-30T00:25:09Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Modelagem bidimensional */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial caótico do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de shape gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
def FTCS(p,m,k1,k2,l,k3,v):&lt;br /&gt;
    N = p.shape[0]&lt;br /&gt;
    &lt;br /&gt;
    p_ = np.zeros(N)&lt;br /&gt;
    m_ = np.zeros(N)&lt;br /&gt;
    &lt;br /&gt;
    for j in np.arange(0,N):&lt;br /&gt;
        back = (j-1)%N&lt;br /&gt;
        forward = (j+1)%N&lt;br /&gt;
        p_[j] = (1 - 2*k1 - k2*(m[back] - m[j]))*p[j] + k1*(p[back]+p[forward]) - k2*(m[forward] - m[j])*p[forward]&lt;br /&gt;
        m_[j] = (1 - l - k3)*m[j] + k3*(m[back] + m[forward]) + v*p[j]&lt;br /&gt;
    return p_,m_&lt;br /&gt;
&lt;br /&gt;
def plot(p,m,filename):&lt;br /&gt;
    #Plota o estado final do sistema em um arquivo&lt;br /&gt;
    fig,ax = plt.subplots(2,1)&lt;br /&gt;
    &lt;br /&gt;
    #População&lt;br /&gt;
    ax[0].set_title(&amp;quot;População&amp;quot;)&lt;br /&gt;
    ax[0].plot(p)&lt;br /&gt;
&lt;br /&gt;
    #Renda&lt;br /&gt;
    ax[1].set_title(&amp;quot;Renda&amp;quot;)&lt;br /&gt;
    ax[1].plot(m)&lt;br /&gt;
&lt;br /&gt;
    plt.savefig(filename + &amp;quot;.png&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DECLARAÇÃO DE CONSTANTES&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
N = 100  #Tamanho do eixo x&lt;br /&gt;
dx = 1&lt;br /&gt;
dt = 0.3&lt;br /&gt;
Dm = 1.0  #Constante de difusão p/ renda.&lt;br /&gt;
Dp = 1.0  #Constante de difusão p/ população.&lt;br /&gt;
gamma = 1.0&lt;br /&gt;
alpha = 1.0&lt;br /&gt;
beta = 1.0&lt;br /&gt;
&lt;br /&gt;
k1 = Dp*dt/(dx**2)&lt;br /&gt;
k2 = gamma*k1/Dp&lt;br /&gt;
k3 = Dm*dt/(dx**2)&lt;br /&gt;
v = alpha*dt&lt;br /&gt;
l = beta*dt&lt;br /&gt;
##########################################################################################&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 1: População e dinheiro em pontos separados&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em 1 ponto da rede longe do ponto da população.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p = np.zeros(N)&lt;br /&gt;
p[20] = 1&lt;br /&gt;
    &lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
m[80] = 1&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 2: Sem dinheiro p/ t = 0&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa totalmente concentrada em 1 ponto da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa zerado&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.zeros(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
##########################################################################################&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
print(&amp;quot;Caso 3: Rede aleatória&amp;quot;)&lt;br /&gt;
print(&amp;quot;População começa distribuída aleatoriamente sobre a rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;Dinheiro começa totalmente focado em um ponto no meio da rede.&amp;quot;)&lt;br /&gt;
print(&amp;quot;=================================================================================&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
N_simulations = 500  #Número de simulações desejado.&lt;br /&gt;
T = N_simulations * dt  #Tempo máximo de duração da simulação.&lt;br /&gt;
&lt;br /&gt;
#Setando população para t = 0&lt;br /&gt;
p1 = np.random.rand(N)&lt;br /&gt;
p = p / np.sum(p)&lt;br /&gt;
&lt;br /&gt;
#Setando renda para t = 0&lt;br /&gt;
m = np.random.rand(N)&lt;br /&gt;
&lt;br /&gt;
for t in np.arange(0,T,dt):&lt;br /&gt;
    p,m = FTCS(p,m,k1,k2,l,k3,v)&lt;br /&gt;
&lt;br /&gt;
#Criação da figura com o estado final&lt;br /&gt;
plot(p,m,&amp;quot;caso_3&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class KellerSegelModel():&lt;br /&gt;
    def __init__(self, parametros):&lt;br /&gt;
        self.parametros = parametros&lt;br /&gt;
&lt;br /&gt;
        self.zeros = np.matrix(np.zeros((parametros.N_x, parametros.N_y)))&lt;br /&gt;
&lt;br /&gt;
        self.tempo = 0&lt;br /&gt;
&lt;br /&gt;
    def contagemPopulacao(self):&lt;br /&gt;
        return self.estado_populacao.sum()&lt;br /&gt;
&lt;br /&gt;
    def contagemDinheiro(self):&lt;br /&gt;
        return self.estado_dinheiro.sum()&lt;br /&gt;
&lt;br /&gt;
    def setEstadoInicial(self, matriz_populacao, matriz_dinheiro):&lt;br /&gt;
        self.estado_populacao = np.matrix(matriz_populacao)&lt;br /&gt;
        self.estado_dinheiro = np.matrix(matriz_dinheiro)&lt;br /&gt;
&lt;br /&gt;
    def getEstado(self):&lt;br /&gt;
        return (self.estado_populacao, self.estado_dinheiro, self.tempo)&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstado(self):&lt;br /&gt;
        # Pega o estado atual da população e dinheiro&lt;br /&gt;
        pn = self.estado_populacao&lt;br /&gt;
        mn = self.estado_dinheiro&lt;br /&gt;
&lt;br /&gt;
        # Inicializa as variáveis que receberão o estado seguinte&lt;br /&gt;
        pn1 = self.zeros.copy()&lt;br /&gt;
        mn1 = self.zeros.copy()&lt;br /&gt;
&lt;br /&gt;
        k1 = self.parametros.k1&lt;br /&gt;
        k2 = self.parametros.k2&lt;br /&gt;
        k3 = self.parametros.k3&lt;br /&gt;
        lamb = self.parametros.lamb&lt;br /&gt;
        v = self.parametros.v&lt;br /&gt;
&lt;br /&gt;
        # Realiza o FTCS&lt;br /&gt;
        for i in np.arange(0, self.parametros.N_x):&lt;br /&gt;
            i_previous = (i - 1) % self.parametros.N_x # Garante que em i == 0 o item anterior seja o último da lista&lt;br /&gt;
            i_next = (i + 1) % self.parametros.N_x # Garante que em i == N_x o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
            for j in np.arange(0, self.parametros.N_y):&lt;br /&gt;
                j_previous = (j - 1) % self.parametros.N_y # Garante que em j == 0 o item anterior seja o último da lista&lt;br /&gt;
                j_next = (j + 1) % self.parametros.N_y # Garante que em j == N_y o item posterior seja o primeiro da lista&lt;br /&gt;
&lt;br /&gt;
                pn1[(i, j)] = pn[(i, j)] * (1 - 4 * k1 - k2 * (mn[(i_previous, j)] - 2 * mn[(i, j)] + mn[(i, j_previous)])) \&lt;br /&gt;
                            + k1 * (pn[(i_previous, j)] + pn[(i, j_previous)] + pn[(i_next, j)] + pn[(i, j_next)]) \&lt;br /&gt;
                            - k2 * (pn[(i_next, j)] * (mn[(i_next, j)] - mn[(i, j)]) + pn[(i, j_next)] * (mn[(i, j_next)] - mn[(i, j)]))&lt;br /&gt;
&lt;br /&gt;
                mn1[(i, j)] = mn[(i, j)] * (1 - 4 * k3 - lamb) + k3 * (mn[(i_previous, j)] + mn[(i, j_previous)] + mn[(i_next, j)] + mn[(i, j_next)]) + v * pn[(i, j)]&lt;br /&gt;
&lt;br /&gt;
        self.estado_populacao = pn1 # Atualiza o estado da população&lt;br /&gt;
        self.estado_dinheiro = mn1 # Atualiza o estado do dinheiro&lt;br /&gt;
        self.tempo += self.parametros.dt # Atualiza o tempo decorrido no modelo&lt;br /&gt;
&lt;br /&gt;
    def atualizaEstadoMultiplasVezes(self, n = 1):&lt;br /&gt;
        for _ in range(0, n):&lt;br /&gt;
            self.atualizaEstado()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
* Sayama, H. '''Introduction to the Modeling and Analysis of Complex Systems'''. 2015&lt;br /&gt;
&lt;br /&gt;
* Scherer, C. '''Métodos Computacionais da Física'''. 2010&lt;br /&gt;
&lt;br /&gt;
* Hoffmann, F. C. O. '''Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis ''', Tese de doutorado. 2017[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3447</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3447"/>
		<updated>2021-03-30T00:10:32Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Programas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial caótico do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de shape gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
* '''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
* Sayama, H. '''Introduction to the Modeling and Analysis of Complex Systems'''. 2015&lt;br /&gt;
&lt;br /&gt;
* Scherer, C. '''Métodos Computacionais da Física'''. 2010&lt;br /&gt;
&lt;br /&gt;
* Hoffmann, F. C. O. '''Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis ''', Tese de doutorado. 2017[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3446</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3446"/>
		<updated>2021-03-30T00:10:07Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial caótico do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de shape gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema. Além disso, foi utilizado PBC.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
'''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
* Sayama, H. '''Introduction to the Modeling and Analysis of Complex Systems'''. 2015&lt;br /&gt;
&lt;br /&gt;
* Scherer, C. '''Métodos Computacionais da Física'''. 2010&lt;br /&gt;
&lt;br /&gt;
* Hoffmann, F. C. O. '''Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis ''', Tese de doutorado. 2017[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3445</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3445"/>
		<updated>2021-03-30T00:07:38Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Programas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
==== População e renda iniciados aleatoriamente na rede ====&lt;br /&gt;
&lt;br /&gt;
Sob a perspectiva de testar a formação de clusters de população, foi criada uma rede completamente aleatória, sem nenhum viés, seja populacional ou econômico. Para isto, tanto população quanto renda possuem valores aleatórios para &amp;lt;math&amp;gt; t = 0 &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Random population.png|thumb|1000px|center|Resultados da simulação para rede iniciada com população e renda aleatórias em t = 0.]]&lt;br /&gt;
&lt;br /&gt;
Enquanto que a primeira coluna de gráficos mostra o estado inicial caótico do sistema, a segunda coluna (t = 9.9) indica exatamente o esperado: 5 clusters bem visíveis são formados para a população. Nota-se, entretanto, que os mesmos 5 picos não são tão visíveis no gráfico de rendas. Uma explicação para isto seria que, mais uma vez, com os valores de desvio padrão da distribuição mais elevados, um pico acaba se sobrepondo a outro, tornando as distribuições difícies de se distinguir.&lt;br /&gt;
&lt;br /&gt;
Conforme a simulação avança no tempo, é perceptível também a tendência entre os picos de se mergirem. E, como visto anteriormente, para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt;, a tendência é que o sistema colapse para um estado com somente um pico de shape gaussiano na população, e um pico na renda, com desvio padrão maior. &lt;br /&gt;
&lt;br /&gt;
Com isso, conclui-se que a formação destes clusters é, de fato, inerente ao sistema, e consequência do modelo utilizado.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
Nota-se que, independente do caso 1D ou 2D, as conclusões tiradas dos modelos construídos se assemelham bastante. Assim como previsto pela teoria de Keller e Segel, base deste estudo, observa-se a formação de clusters de densidade populacional e de renda a partir do momento em que se inicia a simulação, para um intervalo de tempo suficientemente grande a ponto de que estes sejam formados. E essa tendência independe das condições iniciais apresentadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Também foi observado, para ambas as análises, a tendência da função que representa a renda da rede em seguir o comportamento da função que descreve a densidade populacional, algo que também é previsto pelo modelo natural de Keller e Segel, visto que cada foco de população é considerado também um foco de criação de renda por definição.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por último, apesar deste modelo não ser ideal na simulação de sistemas reais população-renda, pois deixa de fora várias variáveis importantes para manter um modelo realista, algumas conclusões obtidas aqui podem ser observadas no mundo real. É o caso da distribuição populacional gaussiana por exemplo, que modela convincentemente a população, a nível macro-geográfico, em centros urbanos, assim como a concentração monetária ser intimamente ligada com a concentração da população. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um estudo mais aplicado sob a estabilidade do método, algo que não é ponto de foco deste trabalho, pode possibilitar a exploração de novas combinações de parâmetros do modelo, vindo a surgir análises sob pontos de vista diferentes.&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
'''Código disponível da plataforma GitHub'''[https://github.com/leonardob17/keller-segel]&lt;br /&gt;
&lt;br /&gt;
=== Modelagem unidimensional ===&lt;br /&gt;
&lt;br /&gt;
=== Modelagem bidimensional ===&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
* Sayama, H. '''Introduction to the Modeling and Analysis of Complex Systems'''. 2015&lt;br /&gt;
&lt;br /&gt;
* Scherer, C. '''Métodos Computacionais da Física'''. 2010&lt;br /&gt;
&lt;br /&gt;
* Hoffmann, F. C. O. '''Keller-Segel-Type Models and Kinetic Equations for Interacting Particles: Long-Time Asymptotic Analysis ''', Tese de doutorado. 2017[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3275</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3275"/>
		<updated>2021-03-29T02:22:54Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{n+10}_{i,j}  -  m^n_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
Falar que um estudo sobre a estabilidade do método pode possibilitar a exploração de novos parâmetros &amp;lt;math&amp;gt;D_p, D_m, \alpha, \beta, \gamma, ds, dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3274</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3274"/>
		<updated>2021-03-29T02:22:29Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{t+10}_{i,j}  -  m^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
Falar que um estudo sobre a estabilidade do método pode possibilitar a exploração de novos parâmetros &amp;lt;math&amp;gt;D_p, D_m, \alpha, \beta, \gamma, ds, dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3273</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3273"/>
		<updated>2021-03-29T02:22:14Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(m^{t+10}_{i,j}  -  mf^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
Falar que um estudo sobre a estabilidade do método pode possibilitar a exploração de novos parâmetros &amp;lt;math&amp;gt;D_p, D_m, \alpha, \beta, \gamma, ds, dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3272</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3272"/>
		<updated>2021-03-29T02:00:33Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* Discussão */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(f^{t+10}_{i,j}  -  f^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
Falar que um estudo sobre a estabilidade do método pode possibilitar a exploração de novos parâmetros &amp;lt;math&amp;gt;D_p, D_m, \alpha, \beta, \gamma, ds, dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3271</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3271"/>
		<updated>2021-03-29T01:58:36Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(f^{t+10}_{i,j}  -  f^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3270</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3270"/>
		<updated>2021-03-29T01:58:25Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(f^{t+10}_{i,j}  -  f^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3269</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3269"/>
		<updated>2021-03-29T01:58:00Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(f^{t+10}_{i,j}  -  f^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1e-9&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
	<entry>
		<id>http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3268</id>
		<title>Modelo de Keller-Segel para relação população-economia</title>
		<link rel="alternate" type="text/html" href="http://fiscomp.if.ufrgs.br/index.php?title=Modelo_de_Keller-Segel_para_rela%C3%A7%C3%A3o_popula%C3%A7%C3%A3o-economia&amp;diff=3268"/>
		<updated>2021-03-29T01:57:34Z</updated>

		<summary type="html">&lt;p&gt;Bleo: /* 2D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''' Grupo: Leonardo Barcelos, Luana Bianchi e Rubens Borrasca '''&lt;br /&gt;
&lt;br /&gt;
O objetivo deste trabalho é implementar o modelo de Keller-Segel, que originalmente descreve ''chemotaxis'': movimento de organismo em direção ou contra algum sinal químico, para um sistema englobando população e atividade econômica. O método computacional utilizado para resolver o problema e implementar o modelo foi o FTCS (''Forward Time Centered Space'').&lt;br /&gt;
&lt;br /&gt;
==Modelo de Keller-Segel==&lt;br /&gt;
&lt;br /&gt;
Proposto por Evelyn Fox Keller, física norte-americana, e Lee Aaron Segel, matemático também norte-americano, o modelo de Keller-Segel foi historicamente utilizado para descrever o movimento de bactérias. Introduzido primeiramente em 1970 para descrever a agregação de uma espécie de bolor limoso (ou ''slime mold'') ameboide, ''Dictyostelium discoideum'', o modelo se tornou um dos mais usados nos estudos biológicos-matemáticos. As células deste ''slime mold'' se comportam como amoebas individuais, e se alimentam de bactérias, mas quando a quantidade de comida fica pequena, elas se difundem pelo espaço e então se agregam em formato mais alongado, como o formato das lesmas, para uma migração de longa distância. Keller e Segel desenvolveram um modelo matemático para o processo de agregação, em que a ''chemotaxis'' tem papel crítico na auto-ormanização das células.&lt;br /&gt;
&lt;br /&gt;
Baseados no que já era conhecido sobre esses organismos, Keller e Segel utilizaram as seguintes premissas:&lt;br /&gt;
* As células estão inicialmente distribuídas sobre o espaço de maneira mais ou menos homogênea, com algumas flutuações aleatótias;&lt;br /&gt;
* As células apresentam ''chemotaxis'' em direção ao sinal químico denominado cAMP (''cyclic adenosine monophosphate'');&lt;br /&gt;
* As células produzem moléculas cAMP;&lt;br /&gt;
* As células e as moléculas cAMP difundem pelo espaço;&lt;br /&gt;
* As células não morrem e não se dividem&lt;br /&gt;
&lt;br /&gt;
De forma simplificada, ocultando alguns detalhes biológicos mais complicados a equação de Keller-Segel é a seguinte:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial a}{\partial t} = \mu \nabla^2 a - \chi \nabla \cdot (a \nabla c)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial c}{\partial t} = D \nabla^2 c + f a - k c&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; são respectivamente as variáveis de estado para a concentração de células e a concentração de cMAP. &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; é o parâmetro de mobilidade das células, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; é o parâmetro da ''chemotaxis'' celular, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; é a constante de difusão das moléculas cAMP, &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; é a taxa de secreção de cMAP pelas células, e &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; é a taxa de decaimento das moléculas cMAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Aplicação população-economia===&lt;br /&gt;
&lt;br /&gt;
De forma parecida com as premissas de Keller e Segel, os seguintes pontos são assumidos para modelar a relação entre a população e a atividade econômica:&lt;br /&gt;
* A população não cresce e não decresce ao longo do tempo;&lt;br /&gt;
* A economia é ativada por existir mais pessoas em uma região;&lt;br /&gt;
* Sem pessoas a atividade econômica diminui;&lt;br /&gt;
* População e atividade econômica difundem gradualmente;&lt;br /&gt;
* As pessoas são atraídas por regiões com maior atividade econômica&lt;br /&gt;
&lt;br /&gt;
Traduzindo estes pontos em equações matemáticas, se obtêm as seguintes equações: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial p}{\partial t} = D_p \nabla^2 p - \gamma \nabla \cdot (p \nabla m)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\frac{\partial m}{\partial t} = D_m \nabla^2 m + \alpha p - \beta m&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
em que &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; representa a população e &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; a atividade econômica. &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; é a constante que determina a taxa de produção de atividade econômica per capita, &amp;lt;math&amp;gt;\beta&amp;lt;/math&amp;gt; é a constante da taxa de decaimento da atividade econômica, &amp;lt;math&amp;gt;D_p&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;D_m&amp;lt;/math&amp;gt; são as constantes de difusão da população e da economia respectivamente, e &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; é a constante que afeta a velocidade média do movimento da população.&lt;br /&gt;
 &lt;br /&gt;
Comparando o sistema obtido com o problema original de Keller-Segel, percebe-se que se trocarmos células por pessoas e cMAP por atividade econômica os problemas ficam iguais, e até se poderia denominar como ''moneytaxis'' a migração das pessoas em direção a atividade econômica, como a ''chemotaxis'' descreve o movimento das células em direção ao cAMP.&lt;br /&gt;
&lt;br /&gt;
==Método FTCS==&lt;br /&gt;
O FTCS (''Forward Time Centered Space'', em tradução livre significa &amp;quot;avançado no tempo, centrado no espaço), é um método de discretização de Equações Diferenciais Parciais(EDP). Para a derivada temporal teremos,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial f}{\partial t} \rightarrow \frac{f^{n+1} - f^n}{\Delta t}&amp;lt;/math&amp;gt;&lt;br /&gt;
e para a parte espacial,&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial^2 f}{\partial s^2} \rightarrow \frac{f_{i-1} - 2f_i + f_{i+1}}{(\Delta s)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
onde &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; é uma variável espacial qualquer &amp;lt;math&amp;gt;(x, y, z, ...)&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; é o tempo.&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 1D ===&lt;br /&gt;
Em 1D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \frac{\partial^2 p}{\partial x^2} - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + p \frac{\partial^2 m}{\partial x^2} \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \frac{\partial^2 m}{\partial x^2} + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i}^{n+1} - p_{i}^{n}}{\Delta t} = \frac{D_p}{(\Delta x)^2} \left[ p_{i-1}^{n} - 2 p_{i}^{n} + p_{i+1}^{n} \right] - \frac{\gamma}{(\Delta x)^2} \left[ (p_{i+1}^n - p_{i}^n)(m_{i+1}^n - m_{i}^n) + p_{i}^n (m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i}^{n+1} - m_{i}^{n}}{\Delta t} = \frac{D_m}{(\Delta x)^2} \left[ m_{i-1}^{n} - 2 m_{i}^{n} + m_{i+1}^{n}\right] + \alpha p_{i}^{n} - \beta m_{i}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde o sub-índice &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; se refere à coordenada &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i}^{n+1} = p_{i}^{n} \left[ 1 - 2K_1 - K_2 \left( m_{i-1}^n - m_i^n \right) \right] + K_1 \left[ p_{i-1}^n + p_{i+1}^n \right] - K_2 \left[ p_{i+1}^n (m_{i+1}^n - m_{i}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i}^{n+1} = m_{i}^n \left[ 1 - K_3 - \lambda \right] + K_3 \left[ m_{i-1}^n + m_{i+1}^n \right] + V p_{i}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os termos agrupados são:&lt;br /&gt;
&amp;lt;math&amp;gt;K_1 = \frac{D_p \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_2 = \frac{\gamma \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;K_3 = \frac{D_m \Delta t}{(\Delta x)^2}&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;V = \alpha \Delta t&amp;lt;/math&amp;gt; , &lt;br /&gt;
&amp;lt;math&amp;gt;\lambda = \beta \Delta t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discretização do Modelo de Keller-Segel em 2D ===&lt;br /&gt;
Em 2D o sistema de equações diferenciais parciais será:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial p}{\partial t} = D_p \left[\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2} \right] - \gamma \left[\frac{\partial p}{\partial x} \frac{\partial m}{\partial x} + \frac{\partial p}{\partial y} \frac{\partial m}{\partial y} + p \left(\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{\partial m}{\partial t} = D_m \left[\frac{\partial^2 m}{\partial x^2} + \frac{\partial^2 m}{\partial y^2} \right] + \alpha p - \beta m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Agora utilizando a discretização FTCS e assumindo que &amp;lt;math&amp;gt;\Delta x = \Delta y = \Delta s &amp;lt;/math&amp;gt; teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{p_{i,j}^{n+1} - p_{i,j}^{n}}{\Delta t} = \frac{D_p}{(\Delta s)^2} \left[ (p_{i-1,j}^{n} - 2 p_{i,j}^{n} + p_{i+1,j}^{n}) + (p_{i,j-1}^{n} - 2 p_{i,j}^{n} + p_{i,j+1}^{n})\right] - \frac{\gamma}{(\Delta s)^2} \left[ (p_{i+1,j}^n - p_{i,j}^n)(m_{i+1,j}^n - m_{i,j}^n) + (p_{i,j+1}^n - p_{i,j}^n)(m_{i,j+1}^n - m_{i,j}^n) + p_{i,j}^n \left( (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n}) \right) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{m_{i,j}^{n+1} - m_{i,j}^{n}}{\Delta t} = \frac{D_m}{(\Delta s)^2} \left[ (m_{i-1,j}^{n} - 2 m_{i,j}^{n} + m_{i+1,j}^{n}) + (m_{i,j-1}^{n} - 2 m_{i,j}^{n} + m_{i,j+1}^{n})\right] + \alpha p_{i,j}^{n} - \beta m_{i,j}^{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
onde os sub-índices &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; se referem às coordenadas &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; respectivamente; e o superíndice &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; se refere ao tempo. Reorganizando as equações e agrupando alguns termos teremos:&lt;br /&gt;
:&amp;lt;math&amp;gt;p_{i,j}^{n+1} = p_{i,j}^{n} \left[ 1 - 4K_1 - K_2 \left( m_{i-1, j}^n - 2m_{1, j}^n + m_{i, j-1}^n \right) \right] + K_1 \left[ p_{i-1,j}^n + p_{i,j-1}^n + p_{i+1,j}^n + p_{i,j+1}^n \right] - K_2 \left[ p_{i+1,j}^n (m_{i+1,j}^n - m_{i,j}^n) + p_{i,j+1}^n (m_{i,j+1}^n - m_{i,j}^n) \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m_{i,j}^{n+1} = m_{i,j}^n \left[ 1 - 4K_3 - \lambda \right] + K_3 \left[ m_{i-1,j}^n + m_{i,j-1}^n + m_{i+1,j}^n + m_{i,j+1}^n \right] + V p_{i,j}^n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resultados==&lt;br /&gt;
===1D===&lt;br /&gt;
&lt;br /&gt;
Com o intuito de testar melhor a equação e suas consequências, os resultados foram divididos em várias simulações diferentes.&lt;br /&gt;
&lt;br /&gt;
Para todas as simulações realizadas, exceto onde indicado, os parâmetros utilizados foram os seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
N = 100&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dx = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
dt = 0.3&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_m = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
D_p = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\gamma = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\alpha = 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\beta = 1 &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, foram utilizadas condições periódicas de contorno (PBC) para a solução das equações diferenciais parciais. Deste modo, pode-se pensar no eixo x como uma &amp;quot;rosquinha&amp;quot;, onde, considerando um sistema de tamanho &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, os pontos &amp;lt;math&amp;gt;x=0&amp;lt;/math&amp;gt; e &amp;lt;math&amp;gt;x=N&amp;lt;/math&amp;gt; estão conectados.&lt;br /&gt;
====População e Dinheiro em pontos separados====&lt;br /&gt;
&lt;br /&gt;
Para esta simulação, considera-se que no tempo 0, toda a população está concentrada em 1 ponto &amp;lt;math&amp;gt; x = \mathcal{C}_1&amp;lt;/math&amp;gt;, enquanto todo o dinheiro está em um outro ponto, distante deste, &amp;lt;math&amp;gt; x = \mathcal{C}_2 &amp;lt;/math&amp;gt;. Deste modo, temos as seguintes equações para as condições iniciais:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
p(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_1, \mathcal{C}_1 \in [0,N]\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0)=\left\{\begin{array}{lc} 1, \quad \text{p/}\quad x = \mathcal{C}_2, \mathcal{C}_2 \in [0,N], \mathcal{C}_2 \neq \mathcal{C}_1\\&lt;br /&gt;
0, \quad \text{caso contrario}\end{array}\right.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na figura abaixo, consegue-se observar o resultado da construção do sistema desta maneira:&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Split money pop.png|1000px|thumb|center|Resultados da simulação para o caso de população e dinheiro em pontos separados e distantes na malha]]&lt;br /&gt;
&lt;br /&gt;
Com toda a população concentrada em 1 ponto (&amp;lt;math&amp;gt; x = 20 &amp;lt;/math&amp;gt;), a atividade econômica cresce consideravelmente neste intervalo ao longo do tempo. Em contrapartida, o local que continha todo o dinheiro no começo da simulação (&amp;lt;math&amp;gt; x = 80 &amp;lt;/math&amp;gt;), em pouco tempo tem a sua renda líquida migrada para onde tem uma densidade populacional maior. Essa tendência indica, portanto, que o sistema é construído de tal forma que a atração da população por regiões de alta renda líquida é menor que a atração do sistema monetário de seguir para pontos de alta densidade populacional.&lt;br /&gt;
&lt;br /&gt;
Além disso, outra observação interessante é que nota-se para &amp;lt;math&amp;gt; t \rightarrow \infty&amp;lt;/math&amp;gt; uma tendência inerente da densidade populacional em seguir uma distribuição de shape gaussiano sob a malha. Considerando que a equação que define o movimento populacional com o tempo contém um termo difusivo, e que a solução para uma difusão simples em 1 dimensão também assume um shape gaussiano, este resultado faz sentido. Mas uma coisa interessante é que, depois de se desfazer de seu formato inicial, o total de dinheiro sob a malha tende a seguir a distribuição populacional, porém com um desvio padrão maior (maior abertura na Gaussiana). Essa observação indica que, para centros econômicos (regiões com alto &amp;lt;math&amp;gt; m &amp;lt;/math&amp;gt;) a tendência é que suas periferias também possuam valores altos de renda, apesar da população consideravelmente menor. Além disso, para regiões fora do contorno de centros econômicos (distância maior do que 3 vezes o desvio padrão da gaussiana) a atividade econômica é basicamente nula, assim como a densidade populacional. Este último fato descreve de forma genérica e simplista o comportamento atual observado em metrópoles nos dias de hoje: uma cidade grande possui alto número de habitantes, alta renda, seus contornos também apresentam atividade econômica forte (porém menor que o centro), mas para um raio suficientemente grande, tanto dinheiro quanto população caem exponencialmente.&lt;br /&gt;
&lt;br /&gt;
==== População uniforme e sem dinheiro no sistema para t = 0 ====&lt;br /&gt;
&lt;br /&gt;
Nesta simulação, considera-se que, para t=0, não há dinheiro sob a malha. Deste modo, a equação que descreve o dinheiro no sistema ao longo do tempo pode ser escrita como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
m(x,t=0) = 0, \forall x \in [0,N]&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Além disso, a população é iniciada de forma aleatória sob a malha. Deste modo, não há tendência inicial à formação de centros com alta densidade de população.&lt;br /&gt;
&lt;br /&gt;
Esta forma inicial da população se assemelha muito à proposição inicial que Keller-Segel fizeram para um sistema celular, como descrito acima. Na prática, temos uma concentração homogênea com pequenas flutuações ao longo do eixo.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0.png|1000px|thumb|center|Resultados da simulação para o caso de m(x,t=0)=0, e população iniciada aleatoriamente.]]&lt;br /&gt;
&lt;br /&gt;
Na imagem acima, para t = 0 (início da simulação) compreende-se melhor as condições iniciais do sistema. Enquanto que a população, aleatoriamente distribuída sob o eixo x, se assemelha a um ruído branco, o dinheiro não existe na malha.&lt;br /&gt;
&lt;br /&gt;
Na segunda coluna de imagens, nota-se um ponto interessante: a formação de clusters de população (e consequentemente, de dinheiro). Estes clusters são, na verdade, picos que aparecem no gráfico de p(x,t), e indicam alta concentração da população em pontos específicos. Além dos picos claramente visíveis (um deles próximo a x=50, e outro próximo a x=90) pode-se enxergar, também, sub-picos nas bases destes picos de população. Para t=24.9 e dt=0.3, deduz-se que o sistema, nesta representação, havia passado por 83 iterações até então, o que indica que, durante estas 83 iterações, haviam mais clusters de população em tempos passados, menores porém definidos. E estes &amp;quot;mini-clusters&amp;quot; se agruparam até formar os 2 picos que vemos.&lt;br /&gt;
&lt;br /&gt;
Com o passar do tempo na simulação, nota-se que o comportamento continua, de modo que para a última coluna de figuras é visível que apenas 1 dos picos iniciais se manteve, enquanto o outro foi praticamente inteiro &amp;quot;engolido&amp;quot; pela cauda do maior. Este comportamento de formação de 1 único cluster de população, com shape gaussiano, já havia sido observado na simulação anterior, para &amp;lt;math&amp;gt; t &amp;lt;/math&amp;gt; suficientemente grande.&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:M0 equilibrium.png|1000px|thumb|center|Simulação do mesmo sistema anterior, para t suficientemente grande (t = 270 neste caso) a ponto de chegar em um estado próximo ao equilíbrio, onde as funções que descrevem população e renda do sistema praticamente não se alteram mais com o tempo.]]&lt;br /&gt;
&lt;br /&gt;
A figura acima mostra o que acontece caso deixemos o mesmo sistema apresentado antes evoluir até um estado de equilíbrio, onde não há alterações para a população ou renda do sistema. Neste caso, observa-se com mais clareza uma curva de shape gaussiano, em localização bem próxima àquela que vimos para t=124.8 na figura anterior, tanto para a distribuição da população quanto da renda. E mais uma vez, mesmo que não muito perceptível pois as 2 curvas apresentadas são bem largas, o desvio padrão da curva que descreve a renda aparenta ser maior que o desvio padrão da curva que descreve a população.&lt;br /&gt;
&lt;br /&gt;
===2D===&lt;br /&gt;
Para o caso em duas dimensões, foi utilizada uma distribuição populacional uniforme em todo o espaço. Já a distribuição econômica, no instante '''t=0''' começou da seguinte forma: Em cada canto do espaço foi atribuído um valor de '''0.125''', no centro '''0.2''' e ao redor do centro em 4 pontos '''1'''. A seguir, é confirmado um comportamento que foi observado no caso unidimensional, em que os picos concentrados, após a evolução do sistema, tomam a forma de gaussianas. É possível notar também que a população tende a ''&amp;quot;clusterizar&amp;quot;'' em torno dos locais em que a atividade econômica tinha valores altos no início da simulação. Isso se deve principalmente ao termo que é influenciado pela constante &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; do sistema de EDPs que modela o sistema.&lt;br /&gt;
[[Arquivo:evoluca_2d_keller_segel.png|1366px|thumb|center|Evolução da atividade econômica e da população para população inicial uniformemente distribuída]]&lt;br /&gt;
&lt;br /&gt;
A seguir, foi gerada uma animação com a evolução do sistema até a estabilização da atividade econômica. A estabilidade da atividade econômica foi entendida como &amp;lt;math&amp;gt;max(f^{t+10}_{i,j}  -  f^t_{i,j}) \leqslant \epsilon&amp;lt;/math&amp;gt;, onde &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt; é o valor que regula o erro. Para este caso &amp;lt;math&amp;gt;\epsilon = 1 \times 10^{-9}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Arquivo:Evolucao 2d gif.gif|1000px|thumb|center|Animação da evolução do sistema]]&lt;br /&gt;
&lt;br /&gt;
Os parâmetros utilizados para gerar as imagens foram os seguintes:&lt;br /&gt;
&amp;lt;math&amp;gt;L = 100&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;ds = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;dt = 0.3&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_m = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;D_p = 0.5&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = 1.2&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = 0.03&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Discussão==&lt;br /&gt;
&lt;br /&gt;
==Programas==&lt;br /&gt;
&lt;br /&gt;
==Referências==&lt;br /&gt;
Sayama&lt;br /&gt;
&lt;br /&gt;
Scherrer&lt;br /&gt;
&lt;br /&gt;
[https://francahoffmann.files.wordpress.com/2017/09/thesis_corrected_post_graduation.pdf]&lt;/div&gt;</summary>
		<author><name>Bleo</name></author>
	</entry>
</feed>